客户端架构扩展
Relay 可用于读取和写入本地数据,并充当客户端应用程序中所有数据的单一事实来源。
Relay 编译器完全支持客户端架构扩展,允许您定义本地字段和类型。
目录:
扩展服务器架构
要扩展服务器架构,请在您的 --src
目录中创建一个新的 .graphql
文件。我们将其命名为 ./src/clientSchema.graphql
。此文件需要位于 Relay 配置中 "schemaExtensions"
引用的文件夹中。
此架构描述了可以在客户端查询哪些本地数据。它甚至可以用来扩展现有的服务器架构。
例如,我们可以创建一个名为 Note
的新类型
type Note {
id: ID!
title: String
body: String
}
然后,我们可以扩展服务器架构类型 User
,并添加一个名为 notes
的 Note
列表。
extend type User {
notes: [Note]
}
查询本地状态
访问本地数据与查询 GraphQL 服务器没有区别,尽管您需要在查询中包含至少一个服务器字段。该字段可以来自服务器架构,也可以是与架构无关的,例如内省字段(例如 __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
函数对于此操作非常理想,因为本地状态的写入通常在 mutation 之外执行。
为了建立在之前的示例基础上,让我们尝试从 User
上的 notes
列表中创建、更新和删除 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');
});
}
请注意,由于此记录将由 ExampleQuery
通过 useLazyLoadQuery
进行渲染,因此查询数据将自动保留,不会被垃圾回收。
如果没有任何组件渲染本地数据,并且您想要手动保留它,您可以通过调用 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');
});
}
初始本地状态
所有新的客户端架构字段默认为 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');
});
此页面是否有用?
请通过以下方式帮助我们改进网站: 回答几个简短的问题.