skip to Main Content

I’m trying to update a state calling its setState method from an useEffect, but it’s updating only on the render and the first call to the setState method.

const [filterChanged, setFilterChanged] = useState(false);

useEffect(() => {
    console.log('filterChanged UPDATED', filterChanged);
}, [filterChanged]);

useEffect(() => {
    const sessionFilter = sessionStorage.getItem('test-filter');
    if (sessionFilter === props.selectedFilter) {
        console.log('filter not changed');
        setFilterChanged(false);
    } else {
        console.log('filter changed');
        setFilterChanged(true);
    }

    sessionStorage.setItem('test-filter', props.selectedFilter);
}, [props.selectedFilter]);

I left the console.logs because I can see in the console the filter changed messages but not the updated ones.
I know this is asyncronous but the filterChanged dependant useEffect is not being triggered even a while after calling the setFilterChanged method.

2

Answers


  1. The first useEffect executes twice: initially during the first render, and again when setFilterChanged(true) is called.

    However, if you select the same category, the second useEffect will not execute because the variables in its dependency array do not change. This means filterChanged will remain true.

    Instead of writing setFilterChanged(true), you can write setFilterChanged(!filterChanged).

    If the filter does not change, neither of the useEffect hooks will execute.

    Login or Signup to reply.
  2. Please do not allow the component to retain the value of the state filterChanged. You can reset the state with a key. The sample code below does the same. Please also see the Test run enclosed as well.

    App.js

    import { useState, useEffect } from 'react';
    
    export default function App() {
      const [someState, setSomeState] = useState(null);
      return (
        <>
          <button
            onClick={() => {
              setSomeState(Math.random());
            }}
          >
            Set Some state, check the console
          </button>
          <br />
          <Component selectedFilter={someState} key={Math.random()} />
        </>
      );
    }
    
    function Component(props) {
      const [filterChanged, setFilterChanged] = useState(false);
    
      useEffect(() => {
        console.log('filterChanged UPDATED', filterChanged);
      }, [filterChanged]);
    
      useEffect(() => {
        const sessionFilter = sessionStorage.getItem('test-filter');
        if (sessionFilter === props.selectedFilter) {
          console.log('filter not changed');
          setFilterChanged(false);
        } else {
          console.log('filter changed');
          setFilterChanged(true);
        }
    
        sessionStorage.setItem('test-filter', props.selectedFilter);
      }, [props.selectedFilter]);
    }
    

    Test run

    On load of the App
    Display  - On load of the App

    On clicking the button first time

    Display - On clicking the button first time

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search