Apollo 客户端:在创建过程中进行乐观更新
Posted
技术标签:
【中文标题】Apollo 客户端:在创建过程中进行乐观更新【英文标题】:Apollo client: Making optimistic updates while creation is still in progress 【发布时间】:2019-04-10 08:56:15 【问题描述】:我希望能够在对象仍在创建时对其进行更新。
例如:假设我有一个待办事项列表,我可以在其中添加带有名称的项目。我还希望能够编辑项目名称。
现在假设连接速度较慢的用户创建了一个项目。在这种情况下,我会启动一个创建项目突变并乐观地更新我的 UI。这很好用。目前没问题
现在假设由于网络速度较慢,创建项目突变需要一些时间。在那个时候,用户决定编辑他们刚刚创建的项目的名称。为了获得理想的体验:
-
用户界面应立即更新为新名称
新名称最终应保留在服务器中
我可以通过等待创建突变完成(以便我可以获取项目 ID),然后进行更新名称突变来实现 #2。但这意味着我的部分 UI 将保持不变,直到创建项目突变返回并且更新名称突变的乐观响应开始。这意味着将无法实现 #1。
所以我想知道如何使用 Apollo 客户端同时实现 #1 和 #2。
注意:我不想添加微调器或禁用编辑。我希望应用即使在连接速度较慢的情况下也能做出响应。
【问题讨论】:
在创建的情况下进行乐观更新。如果有更新,请保持突变准备就绪,并在创建操作完成并且您拥有 id 后在后台执行此操作 【参考方案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 来减少用户键入时的请求数。
【讨论】:
【参考方案2】:我认为实现所需效果的最简单方法是实际放弃乐观更新,转而自行管理组件状态。目前我没有足够的能力写出一个完整的例子,但是你的基本组件结构应该是这样的:
<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 )
实际上,您的编辑突变要么在用户提交时立即触发(因为我们已经从我们的创建突变得到响应)......或者用户所做的更改被保留,然后在创建突变完成后发送。
这是一个非常粗略的示例,但应该让您对如何处理这种情况有所了解。最大的缺点是您的组件状态可能会与缓存不同步——您需要确保正确处理错误以防止这种情况发生。
这也意味着如果您想使用此表单进行只是编辑,您需要从缓存中获取数据,然后使用它来填充您的初始状态(即this.state.created
在上面的例子中)。您可以为此使用 Query
组件,只要确保在获得 Query
组件提供的 data
属性之前不渲染实际的 Form
组件。
【讨论】:
以上是关于Apollo 客户端:在创建过程中进行乐观更新的主要内容,如果未能解决你的问题,请参考以下文章
在 Apollo v3 React 客户端 fe-retching 不同查询的情况下如何实现乐观 UI