Archived course lesson
Add useFetchUser Hook
Objective: Create a useFetchUser hook that will allow us to determine user state within react components.
The hook works by having an internal state that is set by looking at the __user object that is saved to the window object. Initially, that __user object is not present so we can use an effect to call the fetchUser function which will fetch the current user from the /api/me api endpoint. We will receive json back and we save that to window.__user.
This example has been adapted from the same official Auth0 repository example application for a (Next.js application)[https://github.com/zeit/next.js/tree/master/examples/auth0] that we used in the previous step.
import { useState, useEffect } from 'react';
import fetch from 'isomorphic-unfetch';
interface MyWindow extends Window {
__user: any;
}
declare var window: MyWindow;
export async function fetchUser(cookie = '') {
if (typeof window !== 'undefined' && window.__user) {
return window.__user;
}
const res = await fetch(
'/api/me',
cookie
? {
headers: {
cookie,
},
}
: {},
);
if (!res.ok) {
delete window.__user;
return null;
}
const json = await res.json();
if (typeof window !== 'undefined') {
window.__user = json;
}
return json;
}
export function useFetchUser({ required } = {}) {
const [loading, setLoading] = useState(
() => !(typeof window !== 'undefined' && window.__user),
);
const [user, setUser] = useState(() => {
if (typeof window === 'undefined') {
return null;
}
return window.__user || null;
});
useEffect(
() => {
if (!loading && user) {
return;
}
setLoading(true);
let isMounted = true;
fetchUser().then((user) => {
// Only set the user if the component is still mounted
if (isMounted) {
// When the user is not logged in but login is required
if (required && !user) {
window.location.href = '/api/login';
return;
}
setUser(user);
setLoading(false);
}
});
return () => {
isMounted = false;
};
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);
return { user, loading };
}