Reputation: 408
I'm building a guard for a React component. The guard takes an Auth0 JWT and checks our API to see if that user exists in our database. If the user does exist, we set userExists
to true
and redirect them to /dashboard
. If the user does not exist, we call postUser
and send them to /complete-profile
.
The problem I'm running into is that the page is rendering before userExists
is properly being set by the fetch call. In other words, if I were to run the below code, the logs would read in this order:
const SomeGuard: FC<SomeGuardProps> = ({ children }) => {
const { isAuthenticated } = useAuth();
const isMountedRef = useIsMountedRef();
const [userExists, setUserExists] = React.useState(true);
const getUser = useCallback( async () => {
try {
var user_exists;
fetch(`https://website.com/user`,
{
headers: {
Authorization: `Bearer DFJKS54DUJ6DD.SDF2KJWEF4NKN3JKw4534.DFSKJ5HSKDJ6HF`,
},
method: 'GET',
},
).then(response => {
if (response.status===200) { // USER EXISTS
console.log("FETCH CALLED 1")
setUserExists(true);
}
else if (response.status===404) { // catch 404 -- USER NOT FOUND
console.log("FETCH CALLED 2")
setUserExists(false);
}
return response.json();
})
}
catch (e) {
console.error(e);
}
}, [isMountedRef]);
const postUser = useCallback( async () => {
// assume this works and sends a POST request to our API
// to create a user
)}
useEffect(() => {
console.log("STEP 1");
getUser();
}, [getUser]);
if (isAuthenticated) {
if (!userExists) {
console.log("USER DOES NOT EXIST");
postUser();
return <Redirect to="/complete-profile" />;
}
else if (userExists) {
console.log("USER DOES EXIST");
return <Redirect to="/dashboard" />;
}
}
if (!isAuthenticated) {
console.log("TRIED TO HIT DASHBOARD WITHOUT BEING LOGGED IN");
return <Redirect to="/login" />;
}
return (
<>
{children}
</>
);
};
SomeGuard.propTypes = {
children: PropTypes.node
};
export default SomeGuard;
Because it renders the page before the fetch
is called, the value that I initially set userExists
to always determines which page is rendered.
Please help! What am I missing here? How can I get the fetch
call to update userExists
before the page is rendered?
Upvotes: 1
Views: 78
Reputation: 370689
Set the initial value of userExists
to something else, like null
, so you can differentiate an unloaded page from a loaded and true / loaded and false page. Then, only render the children once userExists
isn't null:
const [userExists, setUserExists] = React.useState(null);
if (isAuthenticated) {
if (userExists === false) {
console.log("USER DOES NOT EXIST");
postUser();
return <Redirect to="/complete-profile" />;
}
else if (userExists === true) {
console.log("USER DOES EXIST");
return <Redirect to="/dashboard" />;
}
}
return userExists === null ? null : children;
Upvotes: 1