Realm React - v 0.7.0

Realm React ロゴ

Realm React

より優れたアプリを迅速に構築

はじめに

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

完全な例については、 テンプレートをご覧ください。

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 VirtualizedListまたはFlatListdata引数によって直接消費されます。 リストの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は 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を作成し、 RealmProviderrealmRefプロパティを設定します。

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で 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

これらのフックは通常、 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 ( 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を使用して生成