I'm working on a project where useAuthProvider is causing a useEffect to run ever render. How do I avoid this?
const authProvider = useAuthProvider();
const [loading, setLoading] = useState(true);
const [loaded, setLoaded] = useState(false);
const [roles, setRoles] = useState([]);
useEffect(() => {
authProvider()
.then((data) => {
setRoles(data);
setLoaded(true);
})
.catch((err) => {
console.error(err);
})
.finally(() => {
setLoading(false);
});
}, [authProvider]);
Every time this hook runs authProvider is an object so the shallow compare of useEffect will always evaluate to false.
Have tried just pulling the function I need as well.
const {getRoles} = useAuthProvider()
However the getRoles function also will always evaluate to false in the useEffect dependencies because useAuthProvider produces a a new instance of the function on every render.
Seems like it might be a good use case for useCallback. But we run into the exact same issue.
const getRolesCallback = useCallback(
() => authProvider.getRoles(),
[authProvider]
);
useCallback has the exact same dependency check where authProvider evaluates to false and therefore the useCallback refreshes the function and triggers the useEffect again.
I was looking at some of the react-admin code where they actually use useCallback in this way, but I'm not seeing how it's doing anything.
This is from /ra-core/src/auth/useGetPermissions.ts
const useGetPermissions = (): GetPermissions => {
const authProvider = useAuthProvider();
const getPermissions = useCallback(
(params: any = {}) => authProvider.getPermissions(params),
[authProvider]
);
return authProvider ? getPermissions : getPermissionsWithoutProvider;
};
Won't this useCallback be useless because the authProvider dependency will evaluate to false every time? Am I missing something?
Thanks for any help.
As far as I see, you do not need to include authProvider at all in your dependencies, just an empty array [] will do for your use case. An empty array for the dependency (2nd) parameter means the hook will just run on the initial render.