Sets - React Native SDK
On this page
New in version realm@10.5.0
.
A Realm Set is a special object that allows you to store a collection of unique values. Realm Sets are based on JavaScript sets, but can only contain values of a single type and can only be modified within a write transaction. Sets allow you to perform math operations such as finding the union, intersection, or difference between two Sets. To learn more about performing these operations, see the MDN docs for Implementing basic set operations.
Realm Object Models
You can define a Realm object model property type as a Realm Set, in a two ways:
Specify the data type the Set will contain, followed by
<>
.Use object notation and the
type
field for more complicated properties.
1 class Character extends Realm.Object { 2 static schema = { 3 name: 'Character', 4 primaryKey: '_id', 5 properties: { 6 _id: 'objectId', 7 name: 'string', 8 levelsCompleted: 'int<>', 9 inventory: { 10 type: 'set', 11 objectType: 'string', 12 }, 13 }, 14 }; 15 }
1 class Character extends Realm.Object<Character> { 2 _id!: Realm.BSON.ObjectId; 3 name!: string; 4 levelsCompleted!: Realm.Set<number>; 5 inventory!: Realm.Set<string>; 6 7 static schema: ObjectSchema = { 8 name: 'Character', 9 primaryKey: '_id', 10 properties: { 11 _id: 'objectId', 12 name: 'string', 13 levelsCompleted: 'int<>', 14 inventory: { 15 type: 'set', 16 objectType: 'string', 17 }, 18 }, 19 }; 20 }
Create an Object With a Set
To create an object with a Realm Set property, you must create the object within a write transaction. When defining your Realm object, initialize the Realm Set by passing an empty array or an array with your initial values.
Example
In the following example of a CreateInitialCharacters
component, we create
Character
objects with Set properties.
The CreateInitialCharacters
component does the following:
Gets access to an opened realm instance by calling the
useRealm()
hook within the component.Uses React's useEffect hook to call an anonymous function only once with
useEffect
and an empty dependency array. Within the anonymous function, we create two differentCharacter
objects within a write transaction. We set each character'sinventory
andlevelsCompleted
sets as an array with initial values.Retrieves all characters in the realm instance by passing the
Character
class to theuseQuery()
hook.Displays each character's name in the UI as a
Text
element.
1 const CreateInitialCharacters = () => { 2 const realm = useRealm(); 3 useEffect(() => { 4 realm.write(() => { 5 realm.create('Character', { 6 _id: new Realm.BSON.ObjectId(), 7 name: 'AdventurousPlayer', 8 inventory: ['elixir', 'compass', 'glowing shield'], 9 levelsCompleted: [4, 9], 10 }); 11 }); 12 realm.write(() => { 13 realm.create('Character', { 14 _id: new Realm.BSON.ObjectId(), 15 name: 'HealerPlayer', 16 inventory: ['estus flask', 'gloves', 'rune'], 17 levelsCompleted: [1, 2, 5, 24], 18 }); 19 }); 20 }, []); 21 const characters = useQuery(Character); 22 23 return ( 24 <View> 25 {characters.map(character => ( 26 <View key={character._id}> 27 <Text>{character.name}</Text> 28 </View> 29 ))} 30 </View> 31 ); 32 };
1 const CreateInitialCharacters = () => { 2 const realm = useRealm(); 3 useEffect(() => { 4 realm.write(() => { 5 realm.create('Character', { 6 _id: new Realm.BSON.ObjectId(), 7 name: 'AdventurousPlayer', 8 inventory: ['elixir', 'compass', 'glowing shield'], 9 levelsCompleted: [4, 9], 10 }); 11 }); 12 13 realm.write(() => { 14 realm.create('Character', { 15 _id: new Realm.BSON.ObjectId(), 16 name: 'HealerPlayer', 17 inventory: ['estus flask', 'gloves', 'rune'], 18 levelsCompleted: [1, 2, 5, 24], 19 }); 20 }); 21 }, []); 22 const characters = useQuery(Character); 23 24 return ( 25 <View> 26 {characters.map(character => ( 27 <View key={character._id}> 28 <Text>{character.name}</Text> 29 </View> 30 ))} 31 </View> 32 ); 33 };
Add Items to a Set
To add an item to a Set, pass the new value to the Realm.Set.add() method method within a write transaction.
Example
In the following example of a AddInventoryToCharacter
component, we add new
Set elements to the character's inventory.
The AddInventoryToCharacter
component does the following:
Gets access to an opened realm instance by calling the
useRealm()
hook within the component.Creates a state variable called "inventoryItem" that represents the new inventory item to add to the inventory Set.
Retrieves the character by passing the
Character
class to theuseQuery()
hook and running the Collection.filtered() method on the result to filter for characters with the name matching thecharacterName
prop. Then we set the variablecharacter
to the first matching result.Creates a component method
addInventoryItem()
that performs a write transaction that adds an inventory item to the character's inventory by passing theinventoryItem
state variable toRealm.Set.add()
.Renders a
TextInput
that changes theinventoryItem
state variable, and aButton
that calls theaddInventoryItem()
method.
1 const AddInventoryToCharacter = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const character = useQuery( 5 Character, 6 characters => { 7 return characters.filtered(`name = '${characterName}'`); 8 }, 9 [characterName], 10 )[0]; 11 12 const addInventoryItem = () => { 13 realm.write(() => { 14 character?.inventory.add(inventoryItem); 15 }); 16 }; 17 18 return ( 19 <View> 20 <TextInput 21 onChangeText={text => setInventoryItem(text)} 22 value={inventoryItem} 23 /> 24 <Button 25 title='Add Inventory Item' 26 onPress={addInventoryItem} 27 /> 28 </View> 29 ); 30 };
1 const AddInventoryToCharacter = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState(''); 8 const character = useQuery( 9 Character, 10 characters => { 11 return characters.filtered(`name = '${characterName}'`); 12 }, 13 [characterName], 14 )[0]; 15 16 const addInventoryItem = () => { 17 realm.write(() => { 18 character?.inventory.add(inventoryItem); 19 }); 20 }; 21 22 return ( 23 <View> 24 <TextInput 25 onChangeText={text => setInventoryItem(text)} 26 value={inventoryItem} 27 /> 28 <Button 29 title='Add Inventory Item' 30 onPress={addInventoryItem} 31 /> 32 </View> 33 ); 34 };
Check if a Set has Specific Items and Check the Size of a Set
You may want to check for information about your Set, such as its size or if it contains specific item.
To determine if a Set contains a particular value, pass the value to the
Realm.Set.has() method. This method will return
true
if the Set contains the value specified.
To discover how many items are in a Set, you can check its size
property.
Example
In the following example of a QueryCharacterInventory
component, we check
the character's inventory size and if it has a specific item.
The QueryCharacterInventory
component does the following:
Creates a state variable called "inventoryItem" that represents the inventory item that you want to search the character's inventory for.
Uses the
useQuery
hook to perform a query for all characters, and filter the results to only include the characters with the name matching thecharacterName
passed to the component as a prop. Then we get the first matching result.Retrieves the character by passing the
Character
class to theuseQuery()
hook and running the Collection.filtered() method on the result to filter for characters with the name matching thecharacterName
prop. Then we set the variablecharacter
to the first matching result.Creates a component method
queryCharacterInventory
that passes theinventoryItem
state variable toRealm.Set.has()
to check if the character's inventory contains the item. If the character's inventory contains the item, the method alerts that the character has the item. If the character's inventory does not contain the item, the method alerts that the character does not have the item.Renders the character's name, and renders the inventory size using the
size
property of the character's inventory. It also renders aTextInput
that changes theinventoryItem
state variable, and aButton
that calls thequeryCharacterInventory
method.
1 const QueryCharacterInventory = ({characterName}) => { 2 const [inventoryItem, setInventoryItem] = useState(''); 3 const character = useQuery( 4 Character, 5 characters => { 6 return characters.filtered(`name = '${characterName}'`); 7 }, 8 [characterName], 9 )[0]; 10 11 const queryCharacterInventory = () => { 12 const characterDoesHaveItem = character.inventory.has(inventoryItem); 13 if (characterDoesHaveItem) { 14 Alert.alert(`Character has item: ${inventoryItem}`); 15 } else { 16 Alert.alert(`Item not found in character's inventory`); 17 } 18 }; 19 return ( 20 <View> 21 <Text>{character.name}</Text> 22 <Text> 23 Total number of inventory items: {character.inventory.size} 24 </Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Query for Inventory' 31 onPress={queryCharacterInventory} 32 /> 33 </View> 34 ); 35 };
1 const QueryCharacterInventory = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const [inventoryItem, setInventoryItem] = useState(''); 7 const character = useQuery( 8 Character, 9 characters => { 10 return characters.filtered(`name = '${characterName}'`); 11 }, 12 [characterName], 13 )[0]; 14 15 const queryCharacterInventory = () => { 16 const characterDoesHaveItem: Boolean = 17 character.inventory.has(inventoryItem); 18 if (characterDoesHaveItem) { 19 Alert.alert(`Character has item: ${inventoryItem}`); 20 } else { 21 Alert.alert(`Item not found in character's inventory`); 22 } 23 }; 24 return ( 25 <View> 26 <Text>{character.name}</Text> 27 <Text> 28 Total number of inventory items: {character.inventory.size} 29 </Text> 30 <TextInput 31 onChangeText={text => setInventoryItem(text)} 32 value={inventoryItem} 33 /> 34 <Button 35 title='Query for Inventory' 36 onPress={queryCharacterInventory} 37 /> 38 </View> 39 ); 40 };
Remove Set Information
You may want to remove a specific item or all items from a Set.
To remove a specific value from a Set, pass the value to the Realm.Set.delete() method within a write transaction.
To clear the Set, run the Realm.Set.clear() method within a write transaction.
Example
In the following example of a RemoveInventoryFromCharacter
component, we
remove a specific item from the Set and clear the Set of all items.
The RemoveInventoryFromCharacter
component does the following:
Gets access to an opened realm instance by calling the
useRealm()
hook within the component.Creates a state variable called "inventoryItem" that represents the inventory item to remove from the inventory Set.
Creates a component method
removeInventoryItem
that passes theinventoryItem
state variable toRealm.Set.delete()
to remove the item from the character's inventory.Creates a component method
removeAllInventory
that callsRealm.Set.clear()
to remove all items from the character's inventory.Renders a
TextInput
that changes theinventoryItem
state variable, and twoButton
components that call theremoveInventoryItem
andremoveAllInventory
methods, respectively.
1 const RemoveInventoryFromCharacter = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const character = useQuery( 5 Character, 6 characters => { 7 return characters.filtered(`name = '${characterName}'`); 8 }, 9 [characterName], 10 )[0]; 11 12 const removeInventoryItem = () => { 13 realm.write(() => { 14 character?.inventory.delete(inventoryItem); 15 }); 16 }; 17 const removeAllInventory = () => { 18 realm.write(() => { 19 character?.inventory.clear(); 20 }); 21 }; 22 return ( 23 <View> 24 <Text>{character.name}</Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Remove Inventory Item' 31 onPress={removeInventoryItem} 32 /> 33 <Button 34 title='Remove All Inventory' 35 onPress={removeAllInventory} 36 /> 37 </View> 38 ); 39 };
1 const RemoveInventoryFromCharacter = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState(''); 8 const character = useQuery( 9 Character, 10 characters => { 11 return characters.filtered(`name = '${characterName}'`); 12 }, 13 [characterName], 14 )[0]; 15 16 const removeInventoryItem = () => { 17 realm.write(() => { 18 character?.inventory.delete(inventoryItem); 19 }); 20 }; 21 const removeAllInventory = () => { 22 realm.write(() => { 23 character?.inventory.clear(); 24 }); 25 }; 26 return ( 27 <View> 28 <Text>{character.name}</Text> 29 <TextInput 30 onChangeText={text => setInventoryItem(text)} 31 value={inventoryItem} 32 /> 33 <Button 34 title='Remove Inventory Item' 35 onPress={removeInventoryItem} 36 /> 37 <Button 38 title='Remove All Inventory' 39 onPress={removeAllInventory} 40 /> 41 </View> 42 ); 43 };
Traverse a Set
You can traverse a Set to access each item in the Set. To traverse a
Set, use the Set.map()
method or alternative iteration
method.
However, by default the order of the items in a Set is not guaranteed. To traverse a Set in order, you can store the Set's items in a state variable and update that state variable when you add new items to the Set.
Example
In the following example of a TraverseCharacterInventory
component, a
character starts with no inventory items. When the user adds items to the
inventory Set, the component displays each item in the Set in both an
ordered and unordered list.
The TraverseCharacterInventory
component does the following:
Gets access to an opened realm instance by calling the
useRealm()
hook within the component.Creates a state variable called "inventoryItem" that represents the new inventory item to add to the inventory Set.
Creates a state variable called "inventory" that will hold the character's inventory items in order of insertion.
Retrieves the character by passing the
Character
class to theuseQuery()
hook and running the Collection.filtered() method on the result to filter for characters with the name matching thecharacterName
prop. Then we set the variablecharacter
to the first matching result.Creates a component method
addInventoryItem()
that performs a write transaction that adds an inventory item to the character's inventory by passing theinventoryItem
state variable to the Realm.Set.add() method. After the write transaction, the method adds theinventoryItem
to theinventory
array state variable.Renders a
TextInput
that changes theinventoryItem
state variable, and aButton
that calls theaddInventoryItem()
method.Renders a list of the character's inventory items in the order they were added to the Set by iterating through the
inventory
array state variable.Renders a unordered list of the character's inventory by iterating through
character.inventory
.
1 const TraverseCharacterInventory = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const [inventory, setInventory] = useState([]); 5 6 const character = useQuery( 7 Character, 8 characters => { 9 return characters.filtered(`name = '${characterName}'`); 10 }, 11 [characterName], 12 )[0]; 13 14 const addInventoryItem = () => { 15 realm.write(() => { 16 character?.inventory.add(inventoryItem); 17 }); 18 setInventory([...inventory, inventoryItem]); 19 }; 20 21 return ( 22 <View> 23 <Text>{character.name}</Text> 24 <Text>Add an item to the inventory:</Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Add Inventory Item' 31 onPress={addInventoryItem} 32 /> 33 34 <Text>Ordered Inventory:</Text> 35 {inventory.map(item => ( 36 <Text>{item}</Text> 37 ))} 38 39 <Text>Unordered Inventory:</Text> 40 {character.inventory.map(item => ( 41 <Text>{item}</Text> 42 ))} 43 </View> 44 ); 45 };
1 const TraverseCharacterInventory = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState<string>(''); 8 const [inventory, setInventory] = useState<string[]>([]); 9 10 const character = useQuery( 11 Character, 12 characters => { 13 return characters.filtered(`name = '${characterName}'`); 14 }, 15 [characterName], 16 )[0]; 17 18 const addInventoryItem = () => { 19 realm.write(() => { 20 character?.inventory.add(inventoryItem); 21 }); 22 setInventory([...inventory, inventoryItem]); 23 }; 24 25 return ( 26 <View> 27 <Text>{character.name}</Text> 28 <Text>Add an item to the inventory:</Text> 29 <TextInput 30 onChangeText={text => setInventoryItem(text)} 31 value={inventoryItem} 32 /> 33 <Button 34 title='Add Inventory Item' 35 onPress={addInventoryItem} 36 /> 37 38 <Text>Ordered Inventory:</Text> 39 {inventory.map(item => ( 40 <Text>{item}</Text> 41 ))} 42 43 <Text>Unordered Inventory:</Text> 44 {character.inventory.map(item => ( 45 <Text>{item}</Text> 46 ))} 47 </View> 48 ); 49 };