Novidades na versão realm@10.5.0.
Um Conjunto de Realm é um objeto especial que permite armazenar uma coleção de valores únicos. Os conjuntos de Realm baseiam-se em conjuntos JavaScript , mas só podem conter valores de um único tipo e só podem ser modificados dentro de uma transação de gravação. Os conjuntos permitem que você realize operações matemáticas, como encontrar a união, interseção ou diferença entre dois conjuntos. Para saber mais sobre como executar essas operações, consulte os documentos MDN para Implementação de operações básicas definidas.
Realm Object Models
Você pode definir um tipo de propriedade de modelo de objeto Realm como um Conjunto de Realm de duas maneiras:
Especifique o tipo de dados que o conjunto conterá, seguido por
<>.Use a notação de objeto e o campo
typepara propriedades mais complicadas.
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 }
Criar um objeto com um conjunto
Para criar um objeto com uma propriedade Realm Set, você deve criar o objeto dentro de uma transação de escrita. Ao definir seu Objeto de Realm, inicialize o Realm Set passando uma array vazia ou uma array com seus valores iniciais.
Exemplo
No exemplo a seguir de um componente CreateInitialCharacters , criamos objetos Character com propriedades Set.
O componente CreateInitialCharacters faz o seguinte:
Consegue acesso a uma instância de realm aberta chamando o hook
useRealm()dentro do componente.Utiliza o gancho useEffect da React para chamar uma função anônima somente uma vez com
useEffecte uma array de dependência vazia. Na função anônima, criamos dois objetosCharacterdiferentes dentro de uma transação de gravação. Definimos os conjuntosinventoryelevelsCompletedde cada caractere como uma array com valores iniciais.Recupera todos os caracteres na instância do domínio passando a classe
Characterpara o ganchouseQuery().Exibe o nome de cada caractere na interface do usuário como um elemento
Text.
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 };
Adicionar itens a um conjunto
Para adicionar um item a um conjunto, passe o novo valor para o método Realm.Set.add() dentro de uma transação de gravação.
Exemplo
No exemplo a seguir de um componente AddInventoryToCharacter, adicionamos novos elementos de conjunto ao inventário do caractere.
O componente AddInventoryToCharacter faz o seguinte:
Consegue acesso a uma instância de realm aberta chamando o hook
useRealm()dentro do componente.Cria uma variável de estado chamada "inventoryItem" que representa o novo item de inventário a ser adicionado ao conjunto de inventário.
Recupera o caractere passando a classe
Characterpara o ganchouseQuery()e executando o método Collection.filtered() no resultado para filtrar os caracteres com o nome correspondente à propriedadecharacterName. Então definimos a variávelcharacterpara o primeiro resultado correspondente.Cria um método de componente
addInventoryItem()que executa uma transação de gravação que adiciona um item de inventário ao inventário do personagem passando a variável de estadoinventoryItemparaRealm.Set.add().Apresenta um
TextInputque altera a variável de estado doinventoryIteme umButtonque chama o métodoaddInventoryItem().
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 };
Verificar se um conjunto tem itens específicos e verificar o tamanho de um conjunto
Talvez você queira verificar se há informações sobre o seu Conjunto, como o tamanho ou se ele contém um item específico.
Para determinar se um conjunto contém um valor específico, passe o valor para o método Realm.Set.has() método. Esse método retornará true se o conjunto contiver o valor especificado.
Para descobrir quantos itens estão em um Conjunto, você pode verificar sua propriedade size.
Exemplo
No exemplo a seguir de um componente QueryCharacterInventory, verificamos o tamanho do inventário do personagem e se ele tem um item específico.
O componente QueryCharacterInventory faz o seguinte:
Cria uma variável de estado chamada "inventoryItem" que representa o item de inventário para o qual você deseja pesquisar o inventário do personagem.
Usa o hook
useQuerypara realizar uma consulta de todos os caracteres e filtrar os resultados para incluir apenas os caracteres com o nome correspondente aocharacterNamepassado para o componente como uma propriedade. Em seguida, obtemos o primeiro resultado correspondente.Recupera o caractere passando a classe
Characterpara o ganchouseQuery()e executando o método Collection.filtered() no resultado para filtrar os caracteres com o nome correspondente à propriedadecharacterName. Então definimos a variávelcharacterpara o primeiro resultado correspondente.Cria um método componente
queryCharacterInventoryque passa a variável de estadoinventoryItemparaRealm.Set.has()para verificar se o inventário do personagem contém o item. Se o inventário do caractere contiver o item, o método alertará que o caractere tem o item. Se o inventário do caractere não contiver o item, o método alertará que o caractere não tem o item.Distribui o nome do personagem e renderiza o tamanho do inventário utilizando a propriedade
sizedo inventário do personagem. Ele também renderiza umTextInputque altera a variável de estado doinventoryIteme umButtonque chama o métodoqueryCharacterInventory.
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 };
Remover informações do conjunto
Você pode querer remover um item específico ou todos os itens de um conjunto.
Para remover um valor específico de um conjunto, passe o valor para o método Realm.Set.delete() dentro de uma transação de gravação.
Para limpar o conjunto, execute o método Realm.Set.clear() dentro de uma transação de gravação.
Exemplo
No exemplo a seguir de um componente RemoveInventoryFromCharacter, removemos um item específico do conjunto e limpamos o conjunto de todos os itens.
O componente RemoveInventoryFromCharacter faz o seguinte:
Consegue acesso a uma instância de realm aberta chamando o hook
useRealm()dentro do componente.Cria uma variável de estado chamada "inventoryItem" que representa o item de inventário a ser removido do conjunto de inventário.
Cria um método de componente
removeInventoryItemque passa a variável de estadoinventoryItemparaRealm.Set.delete()a fim de remover o item do inventário do personagem.Cria um método de componente
removeAllInventoryque chamaRealm.Set.clear()para remover todos os itens do inventário do personagem.Renderiza um
TextInputque altera a variável de estadoinventoryIteme dois componentesButtonque chamam os métodosremoveInventoryItemeremoveAllInventory, respectivamente.
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 };
Percorrer um conjunto
Você pode percorrer um conjunto para acessar cada item no conjunto. Para percorrer um Set, use o método Set.map() ou o método de iteração alternativo.
No entanto, por padrão, o pedido dos itens em um conjunto não é garantido. Para percorrer um conjunto em ordem, você pode armazenar os itens do conjunto em uma variável de estado e atualizar essa variável de estado ao adicionar novos itens ao conjunto.
Exemplo
No exemplo seguinte de um componente TraverseCharacterInventory, um caractere começa sem itens de inventário. Quando o usuário adiciona itens ao conjunto de inventário, o componente exibe cada item no conjunto em uma lista ordenada e não ordenada.
O componente TraverseCharacterInventory faz o seguinte:
Consegue acesso a uma instância de realm aberta chamando o hook
useRealm()dentro do componente.Cria uma variável de estado chamada "inventoryItem" que representa o novo item de inventário para adicionar ao conjunto de inventário.
Cria uma variável de estado chamada "inventário" que manterá os itens de inventário do personagem em ordem de inserção.
Recupera o caractere passando a classe
Characterpara o ganchouseQuery()e executando o método Collection.filtered() no resultado para filtrar os caracteres com o nome correspondente à propriedadecharacterName. Então definimos a variávelcharacterpara o primeiro resultado correspondente.Cria um método de componente
addInventoryItem()que executa uma transação de gravação que adiciona um item de inventário ao inventário do personagem passando a variável de estadoinventoryItempara o Realm.Set.add() método. Após a transação de gravação, o método adiciona oinventoryItemà variável de estado da arrayinventory.Apresenta um
TextInputque altera a variável de estado doinventoryIteme umButtonque chama o métodoaddInventoryItem().Renderiza uma lista dos itens de inventário do caractere na ordem em que foram adicionados ao Conjunto, iterando por meio da variável de estado da array
inventory.Renderiza uma lista não ordenada do inventário do personagem iterando por
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 };