我希望能够在仍在创建对象时对其进行更新。
例如:说我有一个待办事项清单,可以在其中添加带有名称的项目。我还希望能够编辑项目名称。
现在说连接速度慢的用户创建了一个商品。在那种情况下,我会触发一个创建项目的变异并乐观地更新我的UI。效果很好。到目前为止没有问题
现在让我们说一下,由于网络速度较慢,创建商品突变要花一些时间。在那个时候,用户决定编辑他们刚刚创建的项目的名称。为了获得理想的体验:
我可以通过等待create突变完成(这样我才能获得商品ID),然后进行更新名称突变来实现#2。但这意味着我的UI的一部分将保持不变,直到创建项突变返回并且更新名称突变的乐观响应开始为止。这意味着将无法实现#1。
所以我想知道如何使用Apollo客户端同时实现#1和#2。
注意:我不想添加微调器或禁用编辑。我希望该应用即使在连接速度较慢的情况下也能保持响应速度。
答案 0 :(得分:1)
如果您有权访问服务器,则可以实施upsert
操作,因此可以将所有查询减少为此类查询:
mutation {
upsertTodoItem(
where: {
key: $itemKey # some unique key generated on client
}
update: {
listId: $listId
text: $itemText
}
create: {
key: $itemKey
listId: $listId
text: $itemText
}
) {
id
key
}
}
因此,您将有一系列相同的突变,只是变量不同。因此,可以配置对这一突变的乐观响应。在服务器上,您需要检查带有key
的项目是否已经存在,并分别创建或更新项目
另外,您可能希望使用apollo-link-debounce来减少用户输入时的请求数
答案 1 :(得分:1)
我认为,达到预期效果的最简单方法是实际删除乐观更新,以便自己管理组件状态。我目前没有足够的带宽来编写完整的示例,但是您的基本组件结构如下所示:
<ApolloConsumer>
{(client) => (
<Mutation mutation={CREATE_MUTATION}>
{(create) => (
<Mutation mutation={EDIT_MUTATION}>
{(edit) => (
<Form />
)}
</Mutation>
)}
</Mutation>
)}
</ApolloConsumer>
假设我们只处理一个字段-name
。您的Form
组件的初始状态为
{ name: '', created: null, updates: null }
提交后,表单将执行以下操作:
onCreate () {
this.props.create({ variables: { name: this.state.name } })
.then(({ data, errors }) => {
// handle errors whichever way
this.setState({ created: data.created })
if (this.state.updates) {
const id = data.created.id
this.props.update({ variables: { ...this.state.updates, id } })
}
})
.catch(errorHandler)
}
然后,编辑逻辑如下所示:
onEdit () {
if (this.state.created) {
const id = this.state.created.id
this.props.update({ variables: { name: this.state.name, id } })
.then(({ data, errors }) => {
this.setState({ updates: null })
})
.catch(errorHandler)
} else {
this.setState({ updates: { name: this.state.name } })
}
}
实际上,您的编辑突变要么在用户提交时立即触发(因为我们已经从我们的create突变中获得了响应)...或者用户所做的更改被保留并在创建突变完成后发送。
这是一个非常粗糙的示例,但是应该使您对如何处理这种情况有所了解。最大的缺点是组件状态可能与缓存不同步-您需要确保正确处理错误以防止这种情况。
这也意味着,如果您要使用此表单进行 just 编辑,则需要从缓存中提取数据,然后使用该数据填充初始状态(即{{1 }}。您可以为此使用this.state.created
组件,只需确保没有渲染实际的Query
组件,直到拥有Form
组件提供的data
道具为止。< / p>