如何在突变后强制 App 到 re-render?
How to force App to re-render after mutation?
我有一个使用 Next.js 构建的 React 应用程序。我希望能够登录,然后使应用程序 re-render 以便它尝试获取当前登录的用户。
我的 _app.js
组件用 apollo 提供程序包装并且还有一个获取用户查询:
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>
</>
);
}
}
然后我有一个登录表单,它只是将电子邮件和密码发送到我的 API,然后 returns 带有访问令牌的 set-cookie 令牌 header。
<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>
我可以成功登录,但我希望 Apollo 缓存可以写入用户数据:
{
"data": {
"login": {
"_id": "abcd1234",
"accessToken": "abc123",
"firstName": "First",
"lastName": "Last",
"email": "abcd123@b.com",
"__typename": "User"
}
}
}
当缓存被写入时,我期待 _app.js / ApolloProvider children 到 re-render 因为它们从缓存接收道具。
然后我的获取用户查询应该再次尝试 运行(这次使用 cookie 中设置的访问令牌)并且应该返回一个用户(表示用户已登录)。
为什么我的突变不告诉我的应用 re-render onCompleted?
这是 refetchQueries()
的完美场景:https://www.apollographql.com/docs/angular/features/cache-updates/#refetchqueries
在您的场景中,您可以将此道具传递给您的登录变更组件,以在登录后重新获取 GET_USER
查询。从您的 _app.js
中导出 GET USER
(或者如果您将它放在一个 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
非常适合像这样的简单登录突变,检索成本不会太高。
我有一个使用 Next.js 构建的 React 应用程序。我希望能够登录,然后使应用程序 re-render 以便它尝试获取当前登录的用户。
我的 _app.js
组件用 apollo 提供程序包装并且还有一个获取用户查询:
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>
</>
);
}
}
然后我有一个登录表单,它只是将电子邮件和密码发送到我的 API,然后 returns 带有访问令牌的 set-cookie 令牌 header。
<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>
我可以成功登录,但我希望 Apollo 缓存可以写入用户数据:
{
"data": {
"login": {
"_id": "abcd1234",
"accessToken": "abc123",
"firstName": "First",
"lastName": "Last",
"email": "abcd123@b.com",
"__typename": "User"
}
}
}
当缓存被写入时,我期待 _app.js / ApolloProvider children 到 re-render 因为它们从缓存接收道具。
然后我的获取用户查询应该再次尝试 运行(这次使用 cookie 中设置的访问令牌)并且应该返回一个用户(表示用户已登录)。
为什么我的突变不告诉我的应用 re-render onCompleted?
这是 refetchQueries()
的完美场景:https://www.apollographql.com/docs/angular/features/cache-updates/#refetchqueries
在您的场景中,您可以将此道具传递给您的登录变更组件,以在登录后重新获取 GET_USER
查询。从您的 _app.js
中导出 GET USER
(或者如果您将它放在一个 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
非常适合像这样的简单登录突变,检索成本不会太高。