Apollo graphql 连接的 React 组件没有重新渲染

Posted

技术标签:

【中文标题】Apollo graphql 连接的 React 组件没有重新渲染【英文标题】:Apollo graphql-connected React component isn't rerendering 【发布时间】:2018-02-10 00:00:39 【问题描述】:

我正在构建基于 graphql 的身份验证机制,并且我正在试图弄清楚为什么一个与 graphql 连接的组件在重新登录后没有重新呈现...例如:

/users 我有一个 react-apollo graphql-connected 用户组件,它请求用户列表。 如果没有提供令牌,服务器将返回验证错误;组件将<Redirect> 渲染到/login 路由;成功登录后,登录组件会隐藏令牌并重定向回来。 Users 组件包装器启动 graphql 请求并同时呈现“正在加载...”。当 graphql 请求成功时,它会重新渲染并出现用户,耶。 如果您从该页面注销,/logout 的注销组件会丢弃该令牌,然后重定向回来;用户组件的请求再次获得身份验证错误并将您发送到“/login”。 再次成功登录后,您将返回到“/users”;它再次向服务器发起 graphql 请求(并呈现“正在加载...”),但这一次,当请求成功时,组件不会再次更新。

我可以看到 graphql 请求成功(并且在 Chrome 的调试器中观察到 APOLLO_QUERY_RESULT 操作由 react-apollo 的 reducer 处理并更新存储中的状态)。

我试图找到 React 在哪里检查组件的 props 是否发生了变化,但是我已经足够是一个 React 调试菜鸟了,我还没有弄清楚在 Web 检查器中的哪里可以找到该代码:也许我不明白 React 是如何打包分发的。

我在登录和注销时都清除了 ApolloClient 的存储(通过调用 resetStore()),因为我不想意外重用来自其他身份验证的数据;但是,删除这些调用并不能解决问题。有趣的是(?),如果我通过在graphql() 调用中提供 options: fetchPolicy: 'network-only' 来强制连接绕过缓存,问题就会消失。 (不是一个可行的解决方案 - 我一般都希望从缓存中受益。)

我已经构建了一个精简的示例:https://github.com/bryanstearns/apollo-auth-experiment 并且您可以在 CodeSandbox 中看到它:https://codesandbox.io/s/m4nlpp86j(您可能希望从 https://m4nlpp86j.codesandbox.io/ 的独立浏览器窗口访问正在运行的示例,因为沙盒编辑器有点让 Web 调试扩展行为怪异)。

【问题讨论】:

【参考方案1】:

要解决此问题,请修改您的 graphql HOC 以在选项中包含 notifyOnNetworkStatusChange

export const Users = graphql(usersQuery,  options:  notifyOnNetworkStatusChange: true  )(RawUsers);

我认为您不应该必须这样做——我认为data.loading 应该准确反映您的查询状态,无论该选项是否设置为 true,这与 @987654327 不同@ 但它looks like it's a known bug.

resetStore 而言——它实际上并没有清除您的整个商店,而是清除您的商店重新获取您所有的活动查询。如果你想吹嘘你的商店,因为你已经将 Redux 与 Apollo 集成,最简单的做法是create an action to do that。

您可能还需要考虑基于会话的身份验证机制,而不是依赖客户端来持久化令牌。在服务器端实现非常简单,不仅在客户端需要更少的工作(不必记住在每个请求中都传递令牌),并且可以让您在用户离开后保持登录状态从页面。

【讨论】:

太好了,丹尼尔,谢谢 - 这解决了我的问题,阅读你链接到的问题的历史是......教育:-)。我可能会切换到 cookie 身份验证;这也是我对 localStorage 的第一次实验。令牌确实具有跨多个域工作的优势(尽管这还不是我遇到的问题),并且 Apollo 可以轻松地为所有请求进行全局配置:github.com/bryanstearns/apollo-auth-experiment/blob/…

以上是关于Apollo graphql 连接的 React 组件没有重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Apollo Graphql 客户端和 React 解决“TypeError:无法读取未定义的属性“参数”?

graphql_devise 用于 Rails/Graphql/Apollo/React 中的身份验证。 “字段需要身份验证”错误

React + Apollo:GraphQL 错误数组未传递到组件中

如何使用 React-Apollo 处理 GraphQL 错误?

使用 Express-GraphQL 和 React-Apollo 订阅 GraphQL

react-apollo 没有连接到我的 graphql 本地服务器