admin管理员组文章数量:1429953
I have a React app built using Next.js. I want to be able to login and then cause the app to re-render in order for it to attempt to fetch the current logged in user.
My _app.js
ponent is wrapped with the apollo provider and has a get user Query as well:
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>
</>
);
}
}
I then have a login form which simply sends the email and password to my API which then returns a set-cookie token header with the access token.
<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>
I can successfully log in but I was expecting the Apollo cache to get written to with the user data:
{
"data": {
"login": {
"_id": "abcd1234",
"accessToken": "abc123",
"firstName": "First",
"lastName": "Last",
"email": "[email protected]",
"__typename": "User"
}
}
}
As the cache is getting written to, I was expecting the _app.js / ApolloProvider children to re-render as they receive props from the cache.
My get user Query should then attempt to run again (this time with the access token set in a cookie) and a user should be returned (indicating the user is logged in).
Why is my mutation not telling my app to re-render onCompleted?
I have a React app built using Next.js. I want to be able to login and then cause the app to re-render in order for it to attempt to fetch the current logged in user.
My _app.js
ponent is wrapped with the apollo provider and has a get user Query as well:
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>
</>
);
}
}
I then have a login form which simply sends the email and password to my API which then returns a set-cookie token header with the access token.
<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>
I can successfully log in but I was expecting the Apollo cache to get written to with the user data:
{
"data": {
"login": {
"_id": "abcd1234",
"accessToken": "abc123",
"firstName": "First",
"lastName": "Last",
"email": "[email protected]",
"__typename": "User"
}
}
}
As the cache is getting written to, I was expecting the _app.js / ApolloProvider children to re-render as they receive props from the cache.
My get user Query should then attempt to run again (this time with the access token set in a cookie) and a user should be returned (indicating the user is logged in).
Why is my mutation not telling my app to re-render onCompleted?
Share Improve this question asked Jun 13, 2019 at 16:04 Stretch0Stretch0 9,31315 gold badges94 silver badges159 bronze badges 4-
2
Why not just
setState
? That would cause a re-render – Max Baldwin Commented Jun 13, 2019 at 16:06 - This would cause a re-render within the local ponent. Not the _app.js ponent which is at the top of the ponent tree – Stretch0 Commented Jun 13, 2019 at 16:14
-
I would put the Apollo
Query
into a higher order ponent that is a context provider. Have that context provider keep track of the user's login status. Set state in there. You can have it in your_app.js
– Max Baldwin Commented Jun 13, 2019 at 16:30 - OK but how do I make the query re run after my mutation? I still have to same problem don't I? – Stretch0 Commented Jun 13, 2019 at 16:39
1 Answer
Reset to default 4This is the perfect scenario for refetchQueries()
: https://www.apollographql./docs/angular/features/cache-updates/#refetchqueries
In your scenario, you could pass this prop to your Login mutation ponent to refetch the GET_USER
query after login. Export the GET USER
from your _app.js
(or wherever you're moving it to if you're putting it in a User Hoc). Then in your login mutation:
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 plete
refetchQueries={[{ query: GET_USER }]}
>
{(login, {loading}) => (
<Login
{...this.props}
login={login}
loading={loading}
error={error}
/>
)}
</Mutation>
The other alternative is to use the update
method to manually set it to the cache and then keep a reference to that data or retrieve it from the cache with a cache id so you don't have to fetch more data, but the refetchQueries
is perfect for simple login mutations like this that aren't too expensive to retrieve.
本文标签: javascriptHow to force App to rerender after mutationStack Overflow
版权声明:本文标题:javascript - How to force App to re-render after mutation? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745461284a2659335.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论