I'm experiencing rerenders seemingly as a result of useQuery being called when I don't want it to be.
First load, isAuthenticated's state is instantiated via a function that makes a query to the server to get the userId based on the attached header.
If a valid header is present, isAuthenticated is set to true and therefore useMemo is called (as isAuthenticated is a dependency). useMemo calls setUser, which puts the userId and role into the context, to be passed down through the AuthProvider (in _app, wrapping everything but the ApolloProvider).
I use the userId in the Navbar (via useContext) to get the avatar (and other things in the rest of the app). What I've noticed is that any time I click on something (for example, a separate query filtering products), the CURRENT_USER query in _app is called. And this manifests as the Navbar losing the useId data passed to it for a second, and then reverts back. So, everytime I click on things, my Navbar is rerendering. I don't understand why the CURRENT_USER query keeps being called...
For context, I use the same setup in another app that does not have SSR without issue.
auth.context.js
import React, { useState, useEffect, useMemo} from "react";
import { CURRENT_USER } from "graphql/query/customer.query";
import { gql, useQuery } from "@apollo/client";
import { isBrowser } from "components/helpers/isBrowser";
export const AuthContext = React.createContext({});
export const AuthProvider = ({ children }) => {
const { data, error, loading } = useQuery(CURRENT_USER, {
onCompleted: () => {
console.log("called query", data);
},
ssr: true,
});
const isValidToken = () => {
if (isBrowser) {
const token = localStorage.getItem("token");
if (error) {
return false;
}
if (!loading && !data) {
return false;
}
if (token && data?.currentUser) {
console.log(data.currentUser);
return true;
}
if (!token) {
return false;
}
}
};
const [isAuthenticated, makeAuthenticated] = useState(isValidToken());
const [user, setUser] = useState({});
function authenticate() {
console.log(isAuthenticated);
makeAuthenticated(isValidToken());
}
useEffect(() => {
console.log("attempted to run");
if (data && isAuthenticated) {
setUser(data.currentUser);
console.log("user", user);
}
}, [isAuthenticated]);
function signout() {
makeAuthenticated(false);
localStorage.removeItem("token");
}
return (
<AuthContext.Provider
value={{
isAuthenticated,
authenticate,
signout,
user,
}}
>
{children}
</AuthContext.Provider>
);
};
"@apollo/client": "^3.0.0-beta.44",
"next": "^9.3.6",
"react": "^16.13.1",