跳至主要內容
版本:v18.0.0

客戶端 Schema 擴展

注意

另請參閱導覽中的本地資料更新僅限客戶端的資料章節。

Relay 可用於讀取和寫入本地資料,並作為客戶端應用程式中所有資料的單一事實來源。

Relay 編譯器完全支援客戶端 Schema 的擴展,這讓您可以定義本地欄位和型別。

目錄:

擴展伺服器 Schema

若要擴展伺服器 Schema,請在您的 --src 目錄內建立新的 .graphql 檔案。我們將其命名為 ./src/clientSchema.graphql。此檔案需要位於您的 Relay 設定的 "schemaExtensions" 中引用的資料夾內。

此 Schema 描述可以在客戶端查詢的本地資料。它甚至可以用來擴展現有的伺服器 Schema。

例如,我們可以建立一個名為 Note 的新類型

type Note {
id: ID!
title: String
body: String
}

然後,使用名為 notesNote 清單來擴展伺服器 Schema 類型 User

extend type User {
notes: [Note]
}

查詢本地狀態

存取本地資料與查詢您的 GraphQL 伺服器沒有區別,儘管您需要在查詢中包含至少一個伺服器欄位。該欄位可以是來自伺服器 Schema,也可以是不可知 Schema,例如自省欄位(例如 __typename)。

在此,我們使用 useLazyLoadQuery 透過 viewer 欄位取得目前的 User,以及他們的 ID、名稱和本機的筆記清單。

// Example.js
import * as React from 'react';
import { useLazyLoadQuery, graphql } from 'react-relay';

const Example = (props) => {
const data = useLazyLoadQuery(graphql`
query ExampleQuery {
viewer {
id
name
notes {
id
title
body
}
}
}
`, {});
// ...
}

變更本地狀態

所有本地資料都存在於 Relay Store 中。

可以使用任何 updater 函式來更新本地狀態。

commitLocalUpdate 函式特別適合用於此目的,因為對本地狀態的寫入通常會在突變之外執行。

為了以上一個範例為基礎,讓我們嘗試從 Usernotes 清單中建立、更新和刪除 Note

建立

import {commitLocalUpdate} from 'react-relay';

let tempID = 0;

function createUserNote(environment) {
commitLocalUpdate(environment, store => {
const user = store.getRoot().getLinkedRecord('viewer');
const userNoteRecords = user.getLinkedRecords('notes') || [];

// Create a unique ID.
const dataID = `client:Note:${tempID++}`;

//Create a new note record.
const newNoteRecord = store.create(dataID, 'Note');

// Add the record to the user's list of notes.
user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes');
});
}

請注意,由於此記錄將透過 useLazyLoadQueryExampleQuery 呈現,因此查詢資料將自動保留,且不會被垃圾回收。

如果沒有元件呈現本地資料,而您想要手動保留它,則可以透過呼叫 environment.retain() 來執行此操作

import {createOperationDescriptor, getRequest} from 'relay-runtime';

// Create a query that references that record
const localDataQuery = graphql`
query LocalDataQuery {
viewer {
notes {
__typename
}
}
}
`;

// Create an operation descriptor for the query
const request = getRequest(localDataQuery);
const operation = createOperationDescriptor(request, {} /* variables */);


// Tell Relay to retain this operation so any data referenced by it isn't garbage collected
// In this case, all the notes linked to the `viewer` will be retained
const disposable = environment.retain(operation);


// Whenever you don't need that data anymore and it's okay for Relay to garbage collect it,
// you can dispose of the retain
disposable.dispose();

更新

import {commitLocalUpdate} from 'react-relay';

function updateUserNote(environment, dataID, body, title) {
commitLocalUpdate(environment, store => {
const note = store.get(dataID);

note.setValue(body, 'body');
note.setValue(title, 'title')
});
}

刪除

import {commitLocalUpdate} from 'react-relay';

function deleteUserNote(environment, dataID) {
commitLocalUpdate(environment, store => {
const user = store.getRoot().getLinkedRecord('viewer');
const userNoteRecords = user.getLinkedRecords('notes');

// Remove the note from the list of user notes.
const newUserNoteRecords = userNoteRecords.filter(x => x.getDataID() !== dataID);

// Delete the note from the store.
store.delete(dataID);

// Set the new list of notes.
user.setLinkedRecords(newUserNoteRecords, 'notes');
});
}

初始本地狀態

所有新的客戶端 Schema 欄位預設為 undefined 值。不過,您通常會在查詢本地資料之前設定初始狀態。您可以使用 commitLocalUpdate 的 updater 函式來準備本地狀態。

import {commitLocalUpdate} from 'react-relay';

commitLocalUpdate(environment, store => {
const user = store.getRoot().getLinkedRecord('viewer');

// initialize user notes to an empty array.
user.setLinkedRecords([], 'notes');
});

此頁面是否有幫助?

透過回答幾個快速問題來幫助我們讓網站變得更好 回答幾個快速問題.