Apollo graphql 连接的 React 组件不会重新渲染
Apollo graphql-connected React component isn't rerendering
我正在致力于通过 graphql 构建身份验证机制,并且我正在尝试弄清楚为什么 graphql 连接的组件在重新登录后没有重新呈现...例如:
- 在
/users
我有一个请求用户列表的 react-apollo graphql-connected Users 组件。
- 如果没有提供令牌,服务器将return认证错误;该组件将
<Redirect>
渲染到 /login
路由;成功登录后,登录组件会存储令牌并重定向回来。
- Users 组件包装器启动 graphql 请求并同时呈现 "loading..."。当 graphql 请求成功时,它会重新呈现并出现用户,耶。
- 如果您从该页面注销,
/logout
处的注销组件会丢弃令牌,然后重定向回来;用户组件的请求再次收到身份验证错误并将您发送到“/login”。
- 再次成功登录后,您将返回“/users”;它再次启动对服务器的 graphql 请求(并呈现 "loading..."),但是这次,当请求成功时,组件不会再次更新。
我可以看到 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 (you'll probably want to access the running example from an independent browser window at https://m4nlpp86j.codesandbox.io/ 因为沙盒编辑器有点让 Web 调试扩展行为怪异)。
要解决此问题,请修改您的 graphql HOC 以在选项中包含 notifyOnNetworkStatusChange
。
export const Users = graphql(usersQuery, { options: { notifyOnNetworkStatusChange: true } })(RawUsers);
我认为您不应该 这样做 -- 我认为 data.loading
应该准确反映您的查询状态,而不管该选项是设置为真,不像 data.networkStatus
但它 looks like it's a known bug.
至于 resetStore
-- 它实际上并没有擦除您的整个商店,而是擦掉您的商店 并且 重新获取您所有的活动查询。如果你想炸毁你的商店,因为你已经将 Redux 与 Apollo 集成,最简单的做法是 .
您可能还想考虑基于会话的身份验证机制,而不是依赖客户端来持久化令牌。实现服务器端非常简单,不仅会减少客户端的工作(不必记住在每个请求中传递令牌),而且会让您的用户在离开后保持登录状态来自页面。
我正在致力于通过 graphql 构建身份验证机制,并且我正在尝试弄清楚为什么 graphql 连接的组件在重新登录后没有重新呈现...例如:
- 在
/users
我有一个请求用户列表的 react-apollo graphql-connected Users 组件。 - 如果没有提供令牌,服务器将return认证错误;该组件将
<Redirect>
渲染到/login
路由;成功登录后,登录组件会存储令牌并重定向回来。 - Users 组件包装器启动 graphql 请求并同时呈现 "loading..."。当 graphql 请求成功时,它会重新呈现并出现用户,耶。
- 如果您从该页面注销,
/logout
处的注销组件会丢弃令牌,然后重定向回来;用户组件的请求再次收到身份验证错误并将您发送到“/login”。 - 再次成功登录后,您将返回“/users”;它再次启动对服务器的 graphql 请求(并呈现 "loading..."),但是这次,当请求成功时,组件不会再次更新。
我可以看到 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 (you'll probably want to access the running example from an independent browser window at https://m4nlpp86j.codesandbox.io/ 因为沙盒编辑器有点让 Web 调试扩展行为怪异)。
要解决此问题,请修改您的 graphql HOC 以在选项中包含 notifyOnNetworkStatusChange
。
export const Users = graphql(usersQuery, { options: { notifyOnNetworkStatusChange: true } })(RawUsers);
我认为您不应该 这样做 -- 我认为 data.loading
应该准确反映您的查询状态,而不管该选项是设置为真,不像 data.networkStatus
但它 looks like it's a known bug.
至于 resetStore
-- 它实际上并没有擦除您的整个商店,而是擦掉您的商店 并且 重新获取您所有的活动查询。如果你想炸毁你的商店,因为你已经将 Redux 与 Apollo 集成,最简单的做法是
您可能还想考虑基于会话的身份验证机制,而不是依赖客户端来持久化令牌。实现服务器端非常简单,不仅会减少客户端的工作(不必记住在每个请求中传递令牌),而且会让您的用户在离开后保持登录状态来自页面。