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

客户端架构扩展

注意

另请参阅 本地数据更新仅客户端数据 部分的导览。

Relay 可用于读取和写入本地数据,并充当客户端应用程序中所有数据的单一事实来源。

Relay 编译器完全支持客户端架构扩展,允许您定义本地字段和类型。

目录:

扩展服务器架构

要扩展服务器架构,请在您的 --src 目录中创建一个新的 .graphql 文件。我们将其命名为 ./src/clientSchema.graphql。此文件需要位于 Relay 配置中 "schemaExtensions" 引用的文件夹中。

此架构描述了可以在客户端查询哪些本地数据。它甚至可以用来扩展现有的服务器架构。

例如,我们可以创建一个名为 Note 的新类型

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

然后,我们可以扩展服务器架构类型 User,并添加一个名为 notesNote 列表。

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

此页面是否有用?

请通过以下方式帮助我们改进网站: 回答几个简短的问题.