Realm React - v 0.7.0

Realm React 徽标

Realm React

更快速地构建更卓越的应用程序。

简介

一直以来,在 React Native 应用程序中设置 Realm 都很复杂。 当数据库中的对象发生更改时,重新呈现组件需要手动添加和删除侦听器,这会生成大量样板代码并且容易出错(如果在卸载时正确删除了侦听器)。 该库通过提供React 钩子来缓解这个问题,这些钩子会返回状态感知的 Realm 数据。 因此,对 Realm 数据的任何更改都会导致使用该钩子的组件重新呈现。

有关@realm/react和 Realm 的文档,请访问docs.mongodb.org

安装

此库要求react-native >= 0.59 且realm >= 11

npm:

npm install realm @realm/react

纱线:

yarn add realm @realm/react

尝试一下

这是一个使用 Realm React 编写的简单任务管理器应用程序。 复制到 React Native 应用程序中并试一试!

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 >
);
}

有关完整的示例,请查看我们的模板

Realm 钩子

useRealm

返回由createRealmContextRealmProvider配置的Realm实例。 以下示例说明了如何使用此钩子为组件进行写事务(write transaction)回调。

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

从给定类型返回Realm.Results 。 此钩子将更新集合中任何对象的任何更改,如果集合为空,则返回一个空数组。 此操作的结果可由任何 React Native VirtualizedListFlatListdata参数直接使用。 如果用于列表的renderItem属性的组件用React.Memo包装,则只有修改后的对象会重新呈现。

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}/>
)
}

useObject

返回给定类型和主键的Realm.Object 。 该钩子将更新返回对象上属性的任何更改,如果该对象不存在或已被删除,则返回null

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>
)
}

设置

RealmProvider

要开始使用@realm/react ,必须用RealmProvider包装您的应用程序。 可以使用属性配置RealmProvider 。 至少必须将schema属性设置为其已配置的 Realm 模型。 RealmProvider 的任何子级都能够使用钩子来访问和操作 Realm 数据。 以下示例说明了如何使用任务模型设置 Realm React:

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

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

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

RealmProvider还附带一个回退属性,该属性在等待 Realm 打开时呈现。 对于本地 Realm,这是即时的,但对于同步的 Realm,较大的数据集可能需要一些时间才能同步,尤其是在第一次打开应用程序时。 在这种情况下,建议提供一个加载组件作为后备方案。

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

在某些情况下,可能需要从RealmProvider外部访问已配置的 Realm,实例,实施客户端重置回退。这可以通过创建带有refuseRef 并设置realmRefRealmProvider 属性来完成。

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

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

可能还需要在应用程序中呈现同一 Realm 的多个RealmProvider 。 在这种情况下,标志closeOnUnmount可默认设置为false`` to prevent both Realm instances from closing when one has been removed from the component tree. This is set to true`。

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

动态更新 Realm 配置

可以通过在RealmProvider上设置属性来更新 域 配置。RealmProvider接受所有可能的 Realm 配置属性的属性。

例如,可以根据用户状态设置同步配置:

const [user, setUser] = useState()

//... some logic to get user state

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

useAppAppProvider

只要AppProvider包装您的应用程序, useApp钩子就可以用于访问您的 Realm App 实例。 这应该在RealmProvider之外完成。

AppProvider 用法:

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 用法:

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

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

//...
}

还可以通过appRef属性在AppProvider之外接收对应用程序的引用。 必须将其设置为从useRef返回的 React 引用。

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

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

useUserUserProvider

通过引入UserProvider ,可以将user自动填充到底层 Realm 配置中。 fallback属性可用于提供登录组件。 用户通过身份验证后,将立即呈现子组件。 注销时,将再次显示回退。

UserProvider 用法:

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 用法:

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

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

//...
}

身份验证钩子

以下钩子可用于对应用程序中的用户进行身份验证。 They return authentication operations and a single result object which can be read to track the progress of the current result. 有关特定身份验证方法的更多信息,请参阅对用户进行身份验证文档。

result

身份验证钩子返回具有以下结构的result

{
/**
* 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

这些钩子通常用在UserProviderfallback组件中。

这可用于管理当前登录操作的状态。

logIn

使用Realm.Credentials实例登录。 这允许使用 Realm 支持的任何身份验证机制登录。 如果在用户当前登录时调用此方法,则会切换用户。

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

使用匿名身份验证提供者登录。

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

logInWithApiKey

使用 API 密钥登录。

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

logInWithEmailPassword

使用电子邮件/密码登录。

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

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

logInWithJWT

使用 JSON web token (JWT) 登录。

const {logInWithJWT, result} = useAuth();

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

logInWithGoogle

使用 Google 登录。

const {logInWithGoogle, result} = useAuth();

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

logInWithApple

使用 Apple 登录。

const {logInWithApple, result} = useAuth();

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

logInWithFacebook

使用 Facebook 登录。

const {logInWithFacebook, result} = useAuth();

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

logInWithCustomFunction

使用自定义函数登录。

const {logInWithFunction, result} = useAuth();

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

logOut

注销当前用户。 这将立即导致UserProvider中的fallback进行渲染。

const {logOut, result} = useAuth();

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

useEmailPasswordAuth

此钩子类似于useAuth ,但专门提供了有关电子邮件/密码身份验证的操作。 这包括重置密码和确认用户的方法。 它返回与 相同的result useAuth对象。

logIn

使用电子邮件和密码登录用户的便捷函数 - 用户也可以调用 `logIn(Realm.Credentials.emailPassword(email, 密码))。

使用TypeDoc生成