Apollo 表单状态管理

Posted

技术标签:

【中文标题】Apollo 表单状态管理【英文标题】:Apollo Form State Management 【发布时间】:2019-03-25 18:49:06 【问题描述】:

使用 React Apollo 客户端处理表单状态管理的最常规方法是什么?有太多基本的 apollo 查询和简单的待办事项应用程序的演练,但我没有看到任何一个展示如何处理现实表单。

想象三种不同的用户流程:

    编辑现有实体(更新表单) 通过添加/删除元素来编辑集合(更新表单) 创建新实体(创建表单)

似乎有几个解决方案:

    使用有状态的 React 组件。该有状态表单嵌套在<Query /><Mutation /> 中,或者可以同时访问datamutate。提交时,直接使用mutate 函数提交突变,并(如有必要)成功时手动更新缓存。它可以工作,但需要更复杂的有状态组件。副作用之一是您必须从道具(componentWillReceiveProps 等)计算状态,因为表单需要 query(用于更新表单,以显示当前值)和 mutation,并且可能会收到表单已呈现后的新数据(在重新获取/轮询时)

    使用 Apollo-Link-State 和 @client- 范围查询。这似乎面临与有状态组件相同的所有问题,如果不是更多,因为额外的间接性。创建表单/新实体很直观,因为新实体可以保存在本地缓存中,然后在提交时发送到远程 API,并在成功时自动出现在正常缓存中。但是,更新表单不太直观,因为现在您基本上拥有同一个对象的两个副本。表单还必须切换其真实来源,最初从普通缓存中读取以填充表单,然后在编辑期间写入/读取本地缓存,然后可能在提交后恢复到普通缓存。否则,像 https://www.robinwieruch.de/react-apollo-link-state-tutorial/ 这样的好的解释并没有说明如何发送本地缓存的数据,而是通常只关注仅用于保持本地的数据,例如设备 API 结果和用户配置。

    写入权威/“正常”的 apollo 缓存,直接覆盖 api 获取的数据,然后从缓存中读回以将其提交给远程 API。这似乎对更新表单更有意义,因为该实体只有一个状态,但不适用于新实体,因为该实体还没有 id(虽然我们可以在客户端生成 uuid,我更愿意让后端生成 id),因此 Apollo 缓存不能使用,AFAIK。这样做的另一个问题是用户刚刚提交的表单数据将在 fetch 时被覆盖,如果某些事情不起作用,这可能会令人沮丧。

感谢任何建议、示例或输入 - 提前致谢!

【问题讨论】:

【参考方案1】:

我发现apollo-link-state 在您想要管理完全是客户端的状态而不是您从服务器获取的数据的一部分的情况下更有用。我认为它不太适合管理组件状态,尤其是表单。最有效的方法是将 Apollo 与 Formik 之类的库结合起来。这降低了您的组件的样板和整体复杂性。这是一个粗略的例子:

<Query query=SOME_QUERY />
( loading, data ) => 
  if (loading) return <LoadingIndicator/>
  return (
    <Mutation query=SOME_MUTATION>
      (mutate) => (
        <Formik
          initialValues=_.pick(data.someData, ['foo', 'bar'])
          validate=/** optional validation function or schema **/
          onSubmit=values => mutate( variables: values )
        >
          (formikProps) => (
            <YourFormComponent ...formikProps/>
          )
        </Formik>
      )
    </Mutation>
  )

</Query>

Formik 组件的渲染函数获得了大量的道具,这些道具都被描述为here。您的实际表单组件可以是无状态的,基本上只是渲染传递给它的道具(值、错误、onChange 处理程序等)。 Formik 接受 yup 模式进行验证,这也使得验证输入变得轻而易举。

【讨论】:

非常酷,谢谢,会试一试。您是否发现了 Formik 的任何限制或您必须解决它的案例?如果是这样,你的后备会是一个有状态的香草组件吗? 就我个人而言,我没有遇到任何问题,API 非常灵活且有据可查。如果您不想使用该库或其他类似库,那么是的,有状态组件几乎是您唯一的选择。

以上是关于Apollo 表单状态管理的主要内容,如果未能解决你的问题,请参考以下文章

如何管理 react + apollo 应用程序的状态

Apollo Client 3.0 或 Redux 用于本地状态管理?

为啥我的 Apollo 缓存更新没有反映在我的查询中?

Apollo 中具有本地状态的变量返回数据

Apollo 客户端本地状态 - LoggedIn 查询

设计表单构建器的数据库和状态突变和请求,以与 graphQL、动物数据库、nextJS 和 Apollo 做出反应