Parth Tiwari
Parth Tiwari

Reputation: 486

UseEffect running continuously in React?

I was trying to run a component on initial run i was trying to dispatch the state value to another component

while running useEffect in particular component, useEffect is running continuously UPDATE:

I am having a dropdown too whenever i change from dropdownthe useEffect runs and set the previous value to state

const handleChange = (event) => {
        console.log("Role changing")
        console.log(event.target.value)
        setStates(event.target.value);
        dispatch({
            type: "SettingROLE",
            payload: states
        })
      };
const { dispatch , state: authState  } = useContext(AuthContext);

    const authMenus = JSON.parse(sessionStorage.getItem("menus")) || []

    const [states, setStates] = useState();

useEffect(() => {
        console.log("Inside of header useEffect")
        const roleid = authMenus.roles[0];
        if(roleid) setStates(roleid.role)
        dispatch({
            type: "SettingROLE",
            payload: states
        })
      }, [authMenus.roles , dispatch , states]);

I tried to remove the dependency of the useEffect but then dispatch is not working it does not dispatch the value of state

Upvotes: 0

Views: 1277

Answers (3)

Todd Skelton
Todd Skelton

Reputation: 7239

useEffect runs anytime a value in the dependency array changes. If it's running continuously, it's because a value is changing. Objects are compared by reference, so any value created in the component will have a new reference each time it's rendered.

In this instance, const authMenus = JSON.parse(sessionStorage.getItem("menus")) || [] is going to create a new reference type every time the component renders and that's triggering an infinite loop.

There are a lot of ways to solve the problem depending on what you are wanting to accomplish.

You can parse it outside the component by moving that code above it.

You can add it to its own useEffect like another answer.

You can store it in a useRef, so it doesn't trigger a rerender.

https://reactjs.org/docs/hooks-reference.html#useref

const authMenus = useRef(JSON.parse(sessionStorage.getItem("menus")) || []);

You could also use useMemo if you have dependencies that you want to trigger the value to update.

https://reactjs.org/docs/hooks-reference.html#usememo

const authMenus = useMemo(() => JSON.parse(sessionStorage.getItem("menus")) || [],[someDependency]);

Upvotes: 1

Gaurav Mithas
Gaurav Mithas

Reputation: 75

if you only want to dispatch on initial run,simply passing [] in dependencies should work!

Also, calling setStates inside useEffect is causing infinite loops!You can move the code except dispatch to outside of useEffect

Upvotes: 0

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

You should separate your logic into two useEffect hooks :

useEffect(() => {
       
        dispatch({
            type: "SettingROLE",
            payload: states
        })
      }, [ dispatch , states]);

useEffect(() => {
       
        const roleid = authMenus.roles[0];
        if(roleid) setStates(roleid.role)
      
      }, [authorMenus]);


since you're updating a state that's a dependency which causes an infinite rendering.

Upvotes: 1

Related Questions