跳至主要内容

GraphQL 变异

GraphQL 变异

GraphQL 选择器 将执行初始查询并订阅任何更改。您可以使用 Relay API(例如 useMutation()commitMutation())来更新服务器上的状态。这些更改也将同步并导致 Recoil GraphQL 选择器更新。这允许您将服务器视为真理源,并将选择器视为本地缓存。

变异响应应选择您希望服务器在更新后返回的数据,以便它可以更新本地客户端状态。这是必要的,这样基于该数据的其他 GraphQL 查询和 Recoil 选择器将使用新状态重新渲染。使用 GraphQL 片段来帮助确保您的查询和变异返回相同的数据是一个好习惯。对于更复杂的更新,您可能需要使用 updater 选项。您还可以使用 optimisticResponseoptimisticUpdater 在从服务器获取对变异的响应之前更新本地状态。如果出现错误,乐观更新将回滚。在任何情况下,请确保您的变异使用与您的查询和选择器相同的 Relay 环境。

function MyComponent(props) {
const user = useRecoilValue(userQuery(props.userID));
const [commitEvent] = useMutation(graphql`
mutation UserMutation($input: UsertNameChangeData!) {
user_mutation(data: $input) {
user {
id
name
}
}
}
`);

return (
<div>
<h1>{user.name}</h1>
<button onClick={() => {
commitEvent({
variables: {
input: {
id: props.userID,
name: 'New Name',
},
},
});
}}>Change Name</button>
</div>
);
}

直写缓存

您可以用来更新状态的另一种模式是将 Recoil 选择器视为服务器的本地直写缓存。它是一个可写选择器,因此本地更新将立即反映在 UI 中。如果您提供 GraphQL 变异 信息,那么更新选择器也将启动服务器上的变异。

const userState = graphQLSelector({
key: 'User',
environment: relayFBEnvironmentKey,
query: graphql`
query UserQuery($eventID: ID!, $clientID: ClientID!) {
user(id: $eventID, client_id: $clientID) {
name
timestamp
}
}
`,
variables: id => ({get}) => ({id, clientID: get(clientIDAtom}),
mapResponse: data => data.user,

mutations: {
mutation: graphql`
mutation UserMutation($input: UserNameChangeData!) {
user_mutation(data: $input) {
user {
id
name
}
}
}
`,
variables: newUserData => id => ({input: {id, name: newUserData.name}}),
},
});
function MyComponent() {
const [user, setUser] = useRecoilState(userState);

return (
<div>
<h1>{user.name}</h1>
<button onClick={() => {
setUser(user => ({...user, name: 'New Name'}));
}}>Change Name</button>
</div>
);
}

请注意,当使用 Recoil 作为这样的直写缓存时,Relay 的“乐观响应”概念对于变异来说是不必要的,因为更新选择器将在远程变异提交之前更新 UI。如果服务器发生错误,本地更新将回滚。

本地更新

commitLocalUpdate() Relay API 可用于对 GraphQL 状态进行本地更新,而无需发出网络请求来更新服务器。更新将导致所有订阅受影响查询和选择器的相关组件重新渲染。