更快速地构建更卓越的应用程序。
一直以来,在 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 >
);
}
有关完整的示例,请查看我们的模板。
返回由createRealmContext
和RealmProvider
配置的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>
)
}
从给定类型返回Realm.Results
。 此钩子将更新集合中任何对象的任何更改,如果集合为空,则返回一个空数组。 此操作的结果可由任何 React Native VirtualizedList
或FlatList
的data
参数直接使用。 如果用于列表的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}/>
)
}
返回给定类型和主键的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>
)
}
要开始使用@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,实例,实施客户端重置回退。这可以通过创建带有ref
的useRef
并设置realmRef
的RealmProvider
属性来完成。
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>
)
}
可以通过在RealmProvider
上设置属性来更新 域 配置。RealmProvider
接受所有可能的 Realm 配置属性的属性。
例如,可以根据用户状态设置同步配置:
const [user, setUser] = useState()
//... some logic to get user state
<RealmProvider sync={{ user, partition }}>
useApp
和 AppProvider
只要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>
)
}
useUser
和 UserProvider
通过引入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
这些钩子通常用在UserProvider
的fallback
组件中。
这可用于管理当前登录操作的状态。
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生成