我有一个使用Next.js构建的React应用。我希望能够登录,然后使应用程序重新呈现,以便它尝试获取当前已登录的用户。
我的class MyApp extends App {
render() {
const { Component, pageProps, apolloClient } = this.props;
return (
<>
<Container>
<ApolloProvider client={apolloClient}>
<Query query={GET_USER} fetchPolicy="network-only" errorPolicy="ignore">
{({ loading, data, error }) => console.log("rendering app", data) || (
<>
<Component {...pageProps} user={data && data.me} />
</>
)}
</Query>
</ApolloProvider>
</Container>
</>
);
}
}
组件与apollo提供程序包装在一起,并且还具有一个get用户Query:
<Mutation
mutation={LOGIN}
onError={error => {
this.setState({error: "Incorrect email or password"})
}}
onCompleted={() => {
window.location.reload() // temp solution to cause app to re-render
}}
>
{(login, {loading}) => (
<Login
{...this.props}
login={login}
loading={loading}
error={error}
/>
)}
</Mutation>
然后我有一个登录表单,该表单仅将电子邮件和密码发送到我的API,然后返回带有访问令牌的set-cookie令牌标头。
{
"data": {
"login": {
"_id": "abcd1234",
"accessToken": "abc123",
"firstName": "First",
"lastName": "Last",
"email": "abcd123@b.com",
"__typename": "User"
}
}
}
我可以成功登录,但是我希望Apollo缓存可以写入用户数据:
def test_threading(self):
obj = mommy.make(self.model_class)
def test_concurrency():
self.model_class.objects.get(id=obj.id)
t1 = Thread(target=test_concurrency)
t2 = Thread(target=test_concurrency)
t1.start()
t2.start()
t1.join()
t2.join()
随着高速缓存的写入,我期望_app.js / ApolloProvider子级在从高速缓存接收道具时重新呈现。
然后,我的获取用户查询应该尝试再次运行(这次在cookie中设置了访问令牌),并且应该返回一个用户(指示该用户已登录)。
为什么我的变体不告诉我的应用重新渲染onCompleted?
答案 0 :(得分:1)
这是refetchQueries()
:https://www.apollographql.com/docs/angular/features/cache-updates/#refetchqueries
在您的情况下,您可以将此道具传递给Login突变组件,以在登录后重新获取GET_USER
查询。从GET USER
中导出_app.js
(如果将其放置在User Hoc中,则将其导出到任何位置)。然后在您的登录突变中:
import { GET_USER } from '...'
<Mutation
mutation={LOGIN}
onError={error => {
this.setState({error: "Incorrect email or password"})
}}
onCompleted={() => {
window.location.reload() // temp solution to cause app to re-render
}}
// takes an array of queries to refetch after the mutation is complete
refetchQueries={[{ query: GET_USER }]}
>
{(login, {loading}) => (
<Login
{...this.props}
login={login}
loading={loading}
error={error}
/>
)}
</Mutation>
另一种方法是使用update
方法将其手动设置为高速缓存,然后保留对该数据的引用或使用高速缓存ID从高速缓存中检索它,从而不必获取更多数据数据,但是refetchQueries
非常适合像这样的简单登录突变,这些突变的检索成本并不高。