apollo-link-state writeQuery 不更新缓存中的 ROOT_QUERY,防止重新渲染组件
apollo-link-state writeQuery does't update ROOT_QUERY in cache, preventing re-render component
我正在使用自定义提供程序实施 OAuth。
所以我有 Auth
组件,其中 'componentDidMount:
client.mutate({
mutation: CURRENT_USER_MUTATION,
variables: {
token: (response.data.token.value) || null,
},
});
我的变异看起来像:
gql`
mutation($token: String!) {
CurrentUser(token: $token) @client
}
`;
我有解析器:
defaults: {
current_user: null,
},
resolvers: {
Mutation: {
CurrentUser: (_: any, { token }: { token: string }, { cache }: { cache: Object }): null => {
const { user } = decodeJWT(token);
cache.writeQuery({
query: CURRENT_USER,
data: {
current_user: {
__typename: 'user',
id: user.id,
name: user.name,
level: user.level,
email: user.email,
},
},
});
return cache.readQuery({ query: CURRENT_USER });
},
},
然后发生了一些事情,当我查看 chrome apollo 调试器时,我可以清楚地看到:
所以数据已经在 Apollo 缓存中,但是 ROOT_QUERY
当前用户仍然有 null。
另外,当我尝试像这样使用 react-apollo
Mutation
组件时:
<Mutation mutation={CURRENT_USER_MUTATION}>
{(mutate: Function,): React.Node => {
return (
<button type="button" onClick={(): Function => mutate(({ variables: { token: '123' } }: Object))}>
Do it
</button>
);
}}
</Mutation>
那就完美了。
所以看起来在使用 cache.writeQuery
之后其他 component/cache 没有通知 运行 突变。
我会很感激你的帮助:)
所以最后,我发现问题出在不同的地方:P 我的朋友 Michał 通过在此处制作我的代码的工作示例向我提出了这个建议:https://codesandbox.io/s/l57k8v3o67
所以得出几个结论:
1. 当检测到用户交互时,组件只会 re-fetch/re-render 。因此,例如单击,这就是为什么带有可单击按钮的组件可以工作或向服务器发出某些请求的原因。
- Apollo 几乎没有错误 :) 我有一个名为
<PrivateRoute />
的不同组件,主要是检查我们是否有 current_user 然后重定向或渲染路由,就是这样:https://gist.github.com/bslipek/b11caefba31599e30d498beaf8644cec And this component has a bug with issue from ere: https://github.com/apollographql/apollo-link-state/issues/236
所以基本上,如果您使用对本地状态的查询渲染组件,并且您没有设置 fetchPolicy='cache-first'
Apollo 将回退到默认值。
看起来你的 CurrentUser
变异是错误的。
这应该有效:
Mutation: {
CurrentUser: (_: any, { token }: { token: string }, { cache }: { cache: Object
}): null => {
const { user } = decodeJWT(token);
cache.writeQuery({
query: CURRENT_USER,
data: {
current_user: {
__typename: 'user',
id: user.id,
name: user.name,
level: user.level,
email: user.email,
},
},
});
return {
current_user: {
__typename: 'user',
id: user.id,
name: user.name,
level: user.level,
email: user.email,
},
}
},
我正在使用自定义提供程序实施 OAuth。
所以我有 Auth
组件,其中 'componentDidMount:
client.mutate({
mutation: CURRENT_USER_MUTATION,
variables: {
token: (response.data.token.value) || null,
},
});
我的变异看起来像:
gql`
mutation($token: String!) {
CurrentUser(token: $token) @client
}
`;
我有解析器:
defaults: {
current_user: null,
},
resolvers: {
Mutation: {
CurrentUser: (_: any, { token }: { token: string }, { cache }: { cache: Object }): null => {
const { user } = decodeJWT(token);
cache.writeQuery({
query: CURRENT_USER,
data: {
current_user: {
__typename: 'user',
id: user.id,
name: user.name,
level: user.level,
email: user.email,
},
},
});
return cache.readQuery({ query: CURRENT_USER });
},
},
然后发生了一些事情,当我查看 chrome apollo 调试器时,我可以清楚地看到:
所以数据已经在 Apollo 缓存中,但是 ROOT_QUERY
当前用户仍然有 null。
另外,当我尝试像这样使用 react-apollo
Mutation
组件时:
<Mutation mutation={CURRENT_USER_MUTATION}>
{(mutate: Function,): React.Node => {
return (
<button type="button" onClick={(): Function => mutate(({ variables: { token: '123' } }: Object))}>
Do it
</button>
);
}}
</Mutation>
那就完美了。
所以看起来在使用 cache.writeQuery
之后其他 component/cache 没有通知 运行 突变。
我会很感激你的帮助:)
所以最后,我发现问题出在不同的地方:P 我的朋友 Michał 通过在此处制作我的代码的工作示例向我提出了这个建议:https://codesandbox.io/s/l57k8v3o67
所以得出几个结论: 1. 当检测到用户交互时,组件只会 re-fetch/re-render 。因此,例如单击,这就是为什么带有可单击按钮的组件可以工作或向服务器发出某些请求的原因。
- Apollo 几乎没有错误 :) 我有一个名为
<PrivateRoute />
的不同组件,主要是检查我们是否有 current_user 然后重定向或渲染路由,就是这样:https://gist.github.com/bslipek/b11caefba31599e30d498beaf8644cec And this component has a bug with issue from ere: https://github.com/apollographql/apollo-link-state/issues/236
所以基本上,如果您使用对本地状态的查询渲染组件,并且您没有设置 fetchPolicy='cache-first'
Apollo 将回退到默认值。
看起来你的 CurrentUser
变异是错误的。
这应该有效:
Mutation: {
CurrentUser: (_: any, { token }: { token: string }, { cache }: { cache: Object
}): null => {
const { user } = decodeJWT(token);
cache.writeQuery({
query: CURRENT_USER,
data: {
current_user: {
__typename: 'user',
id: user.id,
name: user.name,
level: user.level,
email: user.email,
},
},
});
return {
current_user: {
__typename: 'user',
id: user.id,
name: user.name,
level: user.level,
email: user.email,
},
}
},