Reputation: 5413
I am trying to use Apollo-client to pull my users info and stuck with this problem:
I have this Container
component responsible for pulling the user's data (not authentication) once it is rendered. User may be logged in or not, the query returns either viewer = null
or viewer = {...usersProps}
.
Container makes the request const { data, refetch } = useQuery<Viewer>(VIEWER);
, successfully receives the response and saves it in the data
property that I use to read .viewer
from and set it as my current user.
Then the user can log-out, once they do that I clear the Container
's user property setUser(undefined)
(not showed in the code below, not important).
The problem occurred when I try to re-login: Call of refetch
triggers the graphql
http request but since it returns the same data that was returned during the previous initial login - useQuery()
ignores it and does not update data
. Well, technically there could not be an update, the data is the same. So my code setUser(viewer);
does not getting executed for second time and user stucks on the login page.
const { data, refetch } = useQuery<Viewer>(VIEWER);
const viewer = data && data.viewer;
useEffect(() => {
if (viewer) {
setUser(viewer);
}
}, [ viewer ]);
That query with the same response ignore almost makes sense, so I tried different approach, with callbacks:
const { refetch } = useQuery<Viewer>(VIEWER, {
onCompleted: data => {
if (data.viewer) {
setUser(data.viewer);
}
}
});
Here I would totally expect Apollo to call the onCompleted
callback, with the same data or not... but it does not do that. So I am kinda stuck with this - how do I make Apollo to react on my query's refetch
so I could re-populate user
in my Container
's state?
Upvotes: 0
Views: 6620
Reputation: 114
This is a scenario where apollo's caches come handy. Client
import { resolvers, typeDefs } from './resolvers';
let cache = new InMemoryCache()
const client = new ApolloClient({
cache,
link: new HttpLink({
uri: 'http://localhost:4000/graphql',
headers: {
authorization: localStorage.getItem('token'),
},
}),
typeDefs,
resolvers,
});
cache.writeData({
data: {
isLoggedIn: !!localStorage.getItem('token'),
cartItems: [],
},
})
LoginPage
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn @client
}
`;
function IsLoggedIn() {
const { data } = useQuery(IS_LOGGED_IN);
return data.isLoggedIn ? <Pages /> : <Login />;
}
onLogin
function Login() {
const { data, refetch } = useQuery(LOGIN_QUERY);
let viewer = data && data.viewer
if (viewer){
localStorage.setItem('token',viewer.token)
}
// rest of the stuff
}
onLogout
onLogout={() => {
client.writeData({ data: { isLoggedIn: false } });
localStorage.clear();
}}
For more information regarding management of local state. Check this out.
Hope this helps!
Upvotes: 2