Realm React - v0.7.0

Logotipo do Realm React

Realm React

Crie aplicativos melhores, com mais rapidez.

Introdução

Configurar o Realm em um aplicativo React Native historicamente foi complexo. A renderização novamente de componentes quando os objetos no banco de dados são alterados requer a adição e remoção manual de ouvintes, o que produz muitos códigos padrão e é sujeito a erros (se os ouvintes forem removidos corretamente na desmontagem). Essa biblioteca facilita isso ao fornecer ganchos React que retornam dados do Realm com reconhecimento de estado. Como consequência, qualquer alteração nos dados do Realm fará com que os componentes que usam o hook sejam renderizados novamente.

A documentação de @realm/react e Realm pode ser encontrada em docs.mongodb.org.

Instalação

Esta biblioteca requer react-native >= 0,59 e realm >= 11

npm:

npm install realm @realm/react

fio:

yarn add realm @realm/react

Experimente

Aqui está um aplicativo gerenciador de tarefas simples escrito com o Realm React. Copie para um aplicativo React Native e experimente!

import React, { useState } from "react";
import { SafeAreaView, View, Text, TextInput, FlatList, Pressable } from "react-native";
import { Realm, RealmProvider, useRealm, useQuery } from '@realm/react'

class Task extends Realm.Object {
_id!: Realm.BSON.ObjectId;
description!: string;
isComplete!: boolean;
createdAt!: Date;

static generate(description: string) {
return {
_id: new Realm.BSON.ObjectId(),
description,
createdAt: new Date(),
};
}

static schema = {
name: 'Task',
primaryKey: '_id',
properties: {
_id: 'objectId',
description: 'string',
isComplete: { type: 'bool', default: false },
createdAt: 'date'
},
};
}

export default function AppWrapper() {
return (
<RealmProvider schema={[Task]}><TaskApp /></RealmProvider>
)
}

function TaskApp() {
const realm = useRealm();
const tasks = useQuery(Task);
const [newDescription, setNewDescription] = useState("")

return (
<SafeAreaView>
<View style={{ flexDirection: 'row', justifyContent: 'center', margin: 10 }}>
<TextInput
value={newDescription}
placeholder="Enter new task description"
onChangeText={setNewDescription}
/>
<Pressable
onPress={() => {
realm.write(() => {
realm.create("Task", Task.generate(newDescription));
});
setNewDescription("")
}}><Text></Text></Pressable>
</View>
<FlatList data={tasks.sorted("createdAt")} keyExtractor={(item) => item._id.toHexString()} renderItem={({ item }) => {
return (
<View style={{ flexDirection: 'row', justifyContent: 'center', margin: 10 }}>
<Pressable
onPress={() =>
realm.write(() => {
item.isComplete = !item.isComplete
})
}><Text>{item.isComplete ? "✅" : "☑️"}</Text></Pressable>
<Text style={{ paddingHorizontal: 10 }} >{item.description}</Text>
<Pressable
onPress={() => {
realm.write(() => {
realm.delete(item)
})
}} ><Text>{"🗑️"}</Text></Pressable>
</View>
);
}} ></FlatList>
</SafeAreaView >
);
}

Para obter um exemplo completo, confira nossos modelos.

Realm Hooks

useRealm

Retorna a instância do Realm configurada por createRealmContext e o RealmProvider. Veja a seguir um exemplo de como usar esse Hook para fazer uma chamada de resposta de transação de escrita para um componente.

import {useRealm} from '@realm/react';
// assume props contain item a Realm.Object
const Component = ({item}) => {
const realm = useRealm();
const toggleComplete = useCallback((item) => {
realm.write(() => {
item.isComplete = !item.isComplete
})
},[item, realm])

return (
<Pressable
onPress={() =>
realm.write(() => {
item.isComplete = !item.isComplete
})
}><Text>{item.isComplete ? "✅" : "☑️"}</Text>
</Pressable>
)
}

useQuery

Retorna Realm.Results de um determinado tipo. Esse Hook atualizará sobre quaisquer alterações em qualquer objeto da Coleção e retornará uma matriz vazia se a Coleção estiver vazia. O resultado disso pode ser consumido diretamente pelo argumento data de qualquer React Native VirtualizedList ou FlatList. Se o componente usado para o suporte renderItem da lista estiver agrupado com React.Memo , somente o objeto modificado será renderizado novamente.

import {useQuery} from '@realm/react';

const Component = () => {
// ObjectClass is a class extending Realm.Object, which should have been provided in the Realm Config.
// It is also possible to use the model's name as a string ( ex. "Object" ) if you are not using class based models.
const sortedCollection = useQuery({
type: ObjectClass,
query: (collection) => {
// The methods `sorted` and `filtered` should be passed as a `query` function.
// Any variables that are dependencies of this should be placed in the dependency array.
return collection.sorted();
}
}, []);

return (
<FlatList data={sortedCollection} renderItem={({ item }) => <Object item={item}/>
)
}

Objeto de uso

Retorna um Realm.Object para um determinado tipo e chave primária. O Hook atualizará quaisquer alterações nas propriedades do objeto retornado e retornará null se ele não existir ou tiver sido excluído.

import {useObject} from '@realm/react';

const Component = ({someId}) => {
// ObjectClass is a class extending Realm.Object, which should have been provided in the Realm Config.
// It is also possible to use the model's name as a string ( ex. "Object" ) if you are not using class based models.
const object = useObject(ObjectClass, someId);

return (
<View>
<Text>{object.name}</Text>
</View>
)
}

Definindo as coisas

Provedor de domínios

Para começar a usar @realm/react, é necessário envolver seu aplicativo com um RealmProvider. O RealmProvider pode ser configurado usando props. No mínimo, deve-se definir o prop schema para os modelos de Realm que eles configuraram. Qualquer filho do RealmProvider poderá usar os hooks para acessar e manipular dados do Realm. Aqui está um exemplo de como configurar o Realm React com um modelo de tarefa:

import { RealmProvider, useQuery, Realm } from '@realm/react';

const AppWrapper = () => {
return (
<RealmProvider schema={[Item]}>
<SomeComponent/>
<RealmProvider>
)
}

const SomeComponent = () => {
const items = useQuery(Item)
//..
}

O RealmProvider também vem com um suporte fallback que é renderizado enquanto aguarda a abertura do Realm. Para o Realm local, isso é instantâneo, mas para um Realm sincronizado, pode levar tempo para que conjuntos de dados maiores sejam sincronizados, especialmente se for a primeira vez que o aplicativo é aberto. Nesse caso, é recomendável fornecer um componente de carregamento como um fallback.

const AppWrapper = () => {
return (
<RealmProvider fallback={<Loading/>} >
<App/>
<RealmProvider>
)
}

Em alguns casos, pode ser necessário acessar o Realm configurado de fora do RealmProvider, por exemplo, implementando um fallback de reinício do cliente. Isso pode ser feito criando um ref com useRef e definindo a propriedade realmRef de RealmProvider.

const AppWrapper = () => {
const realmRef = useRef<Realm|null>(null)

return (
<RealmProvider realmRef={realmRef}>
<App/>
<RealmProvider>
)
}

Também pode ser necessário renderizar vários RealmProviders do mesmo Realm em um aplicativo. Nesse caso, o sinalizador closeOnUnmount pode ser definido como false`` to prevent both Realm instances from closing when one has been removed from the component tree. This is set to true' por padrão.

const AppWrapper = () => {
return (
<RealmProvider closeOnUnmount={false}>
<App/>
<RealmProvider>
)
}

Atualizando dinamicamente uma configuração de Realm

É possível atualizar a configuração do Realm definindo adereços em RealmProvider. O RealmProvider usa acessórios para todas as possíveis propriedade de configuração do Realm.

Por exemplo, pode-se definir a configuração de sincronização com base no estado do usuário:

const [user, setUser] = useState()

//... some logic to get user state

<RealmProvider sync={{ user, partition }}>

useApp e o AppProvider

O hook useApp pode ser usado para acessar a instância do aplicativo Realm, desde que o AppProvider envolva seu aplicativo. Isso deve ser feito fora do seu RealmProvider.

AppProvider uso:

import { AppProvider } from '@realm/react'
//...
// Wrap your RealmProvider with the AppProvider and provide an appId
<AppProvider id={appId}>
<RealmProvider sync={{user, flexible: true}}>
//...
</RealmProvider>
</AppProvider>

useApp uso:

// Access the app instance using the useApp hook
import { useApp } from '@realm/react'

const SomeComponent = () => {
const app = useApp();

//...
}

Também é possível receber uma referência à aplicação fora do AppProvider, através da propriedade appRef . Isso deve ser definido como uma referência React retornada de useRef.

const AppWrapper = () => {
const appRef = useRef<Realm.App|null>(null)

return (
<AppProvider appRef={appRef}>
<App/>
<AppProvider>
)
}

useUser e o UserProvider

Com a introdução do UserProvider, o user pode ser preenchido automaticamente na configuração subjacente do Realm. A propriedade fallback pode ser utilizada para fornecer um componente de login. Os componentes secundários serão renderizados assim que o usuário for autenticado. Ao sair, o fallback será exibido novamente.

UserProvider uso:

import { AppProvider, UserProvider } from '@realm/react'
//...
<AppProvider id={appId}>
<UserProvider fallback={LoginComponent}>
{/* After login, user will be automatically populated in realm configuration */}
<RealmProvider sync={{flexible: true}}>
//...
</RealmProvider>
</UserProvider>
</AppProvider>

useUser uso:

// Access the app instance using the useApp hook
import { useUser } from '@realm/react'

const SomeComponent = () => {
const user = useUser();

//...
}

Hooks de autenticação

Os seguintes ganchos podem ser usados para autenticar usuários em seu aplicativo. Eles retornam operações de autenticação e um único objeto de resultado que pode ser lido para acompanhar o progresso do resultado atual. Mais informações sobre os métodos de autenticação específicos podem ser encontradas na documentação de autenticação de usuários .

result

Os hooks de autenticação retornam um result tem a seguinte estrutura:

{
/**
* The current state of the operation.
* Enumerated by OperationState
*/
state, // "not-started", "pending", "success", "error"

/**
* The string name of the current operation running.
*/
operation,

/**
* Convenience accessors, so users can write e.g. `loginResult.pending`
* instead of `loginResult.state === OperationState.Pending`
*/
pending, // true or false
success, // true or false

/**
* The error returned from the operation, if any. This will only be populated
* if `state === OperationState.Error`, and will be cleared each time the
* operation is called.
*/
error // Error based object or undefined
}

useAuth

Esses ganchos normalmente seriam usados no componente fallback do UserProvider

Isso pode ser usado para gerenciar o estado da operação de login atual.

logIn

Faça login com uma instância Realm.Credentials . Isso permite o login com qualquer mecanismo de autenticação suportado pelo Realm. Se isso for chamado quando um usuário estiver conectado no momento, ele trocará o usuário.

const {logIn, result} = useAuth();

// Log in with a `Realm.Credentials` instance. This allows login with any authentication mechanism supported by Realm.
// If this is called when a user is currently logged in, it will switch the user.
// Typically the other methods from `useAuth` would be used.
// If this is rendered in the fallback of the `UserProvider`,
// then it's children will be rendered as soon as this succeeds.
useEffect( () => logIn(Realm.Credential.anonymous()), [] );
}

if(result.pending) {
return (<LoadingSpinner/>)
}

if(result.error) {
return (<ErrorComponent/>)
}

if(result.success) {
return (<SuccessComponent/>)
}
//...

logInWithAnonymous

Faça login com o provedor de autenticação anônimo.

const {logInWithAnonymous, result} = useAuth();
const performLogin = () => {
logInWithAnonymous();
};

logInWithApiKey

Faça login com uma chave de API.

const {logInWithApiKey, result} = useAuth();
const performLogin = () => {
const key = getApiKey(); // user defined function
logInWithApiKey(key);
};

logInWithEmailPassword

Faça login com e-mail/senha.

const {logInWithEmailPassword, result} = useAuth();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");

const performLogin = () => {
logInWithEmailPassword({email, password});
};

logInWithJWT

Faça login com um JSON web token (JWT).

const {logInWithJWT, result} = useAuth();

const performLogin = () => {
const token = authorizeWithCustomerProvider(); // user defined function
logInWithJWT(token);
};

logInWithGoogle

Faça login com o Google.

const {logInWithGoogle, result} = useAuth();

const performLogin = () => {
const token = getGoogleToken(); // user defined function
logInWithGoogle({idToken: token});
};

logInWithApple

Faça login com a Apple.

const {logInWithApple, result} = useAuth();

const performLogin = () => {
const token = getAppleToken(); // user defined function
logInWithApple(token);
};

logInWithFacebook

Faça login com o Facebook.

const {logInWithFacebook, result} = useAuth();

const performLogin = () => {
const token = getFacebookToken(); // user defined function
logInWithFacebook(token);
};

logInWithCustomFunction

Faça login com uma função personalizada.

const {logInWithFunction, result} = useAuth();

const performLogin = () => {
const customPayload = getAuthParams(); // user defined arguments
logInWithFunction(customPayload);
};

logOut

Desconecte o usuário atual. Isso fará com que o fallback do UserProvider seja imediatamente renderizado.

const {logOut, result} = useAuth();

const performLogOut = () => {
logOut();
};

useEmailPasswordAuth

Esse hook é semelhante ao useAuth, mas oferece especificamente operações de autenticação por e-mail/senha. Isso inclui métodos para redefinir senhas e confirmar usuários. Ele retorna o mesmo objeto result que useAuth.

logIn

Função de conveniência para conectar um usuário com um e-mail e senha - os usuários também podem chamar `logIn(Realm.Credentials.emailPassword(email, senha)).

Gerado usando TypeDoc