より優れたアプリを迅速に構築
React Native アプリケーションで Realm を設定する設定は、これまで複雑説明されていました。 データベース内の オブジェクトが変更されたときにコンポーネントを再レンダリングするには、リスナーを手動で追加および削除する必要があるため、大量のワーカーレート コードが生成され、エラーが発生しやすくなります(リスナーがアンマウント時に適切に削除された場合)。 このライブラリは、状態を認識する Realm データを返すReact フックを提供することで、その問題を軽減します。 その結果、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
は props を使用して構成できます。 少なくとも、構成した Realm モデルにschema
プロンプトを設定する必要があります。 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 にアクセスする必要がある場合があります。 そのためには、 useRef
を使用してref
を作成し、 RealmProvider
のrealmRef
プロパティを設定します。
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
で props を設定することで、Realm 構成を更新できます。 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();
//...
}
次のフックは、アプリケーション内のユーザーを認証するために使用できます。 認証操作と単一の結果オブジェクトが返され、現在の結果の進行状況を追跡するために読み取れます。 具体的な認証方法の詳細については、「ユーザーの認証」のドキュメントを参照してください。
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 ( JSON web token )でログインします。
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
現在のユーザーをログアウトします。 これにより、fallback
からのUserProvider
がすぐにレンダリングされます。
const {logOut, result} = useAuth();
const performLogOut = () => {
logOut();
};
useEmailPasswordAuth
このフックはuseAuth
と似ていますが、具体的には メール/パスワード認証 に関する操作を提供します。 これには、パスワードのリセットやユーザーの確認に関するメソッドが含まれます。 useAuth
と同じresult
オブジェクトが返されます。
logIn
メールとパスワードを使用してユーザーをログインするための便利な関数 - ユーザーは `logIn(Realm.Credentials.emailPassword(email, パスワード))のどちらでも構いません。
TypeDocを使用して生成