Reputation: 3327
I have a web application, iwth an instance of a keycloack.js, where i tried to use a custom hook, to fetch a userprofile, before the UI renders. The reason for that, is that the actual application requires, some information in localStorage before the ui should render.
Here is the logic i have tried to implement in my App.js
component
import React, {Suspense} from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import 'appkit-react/style/appkit-react.default.css';
import PageHub from './Components/Navigation/PageHub';
import Spinner from './Components/Shared/Spinner';
import LoadUserProfile from './_helpers/hooks/loadUserProfile'
import './i18n';
function App(props) {
const [loading, error] = LoadUserProfile(props.keycloak)
console.log(props)
if(loading){
return <Spinner />
}
if(error){
console.log(error)
return <div>Error occured!!</div>
}
console.log(loading)
console.log(error)
return (
<Suspense fallback={<Spinner/>}>
<PageHub/>
</Suspense>
);
}
export default App;
and the LoadUserProfile
hook looks like this.
import React, { useState, useEffect } from 'react';
import Spinner from '../../Components/Shared/Spinner';
function LoadUserProfile(keycloak){
const [loading, setLoading] = useState(false);
const [error, setError] = useState({});
useEffect(() =>{
setLoading(true)
keycloak.loadUserProfile().success((profile) => {
console.debug('Loaded profile ' + profile);
localStorage.setItem("firstName", keycloak.profile.firstName);
localStorage.setItem("lastName", keycloak.profile.lastName);
localStorage.setItem('GUID', keycloak.profile.attributes.guid[0])
setLoading(false)
}).error(() => {
console.error('Failed to load profile')
setLoading(false)
setError({"error": "No user found"})
}, [keycloak, loading, error]);
})
return [loading, error]
}
export default LoadUserProfile;
right now it goes into an infinite loop.
Upvotes: 0
Views: 548
Reputation: 789
So first of all you must rename your custom hook to useLoadUserProfile as recommended in the React Documentation so that React would be able to automatically check for violations of rules of Hooks. The infinite loop is caused by the inclusion of the loading and error states in your dependency array. Whenever you make a call to 'setMyState' in this case setLoading or setError
So to fix this you must remove the loading and error states from your dependency array. The Rule of thumb is:
if you specify the dependency array, all values from inside your component that are used by the effect must be there. Including props, state, functions — anything in your component. i.e never lie about your dependencies.
In your case your useEffect hook does not even depend on your loading or error states. So they shouldn't be in the dependency array in the first place!
Upvotes: 2