Search code examples
javascriptreactjssetintervalreact-functional-component

Condition inside setInterval in functional component


I set an interval inside useEffect to update data every 33 seconds if a state variable can_update is true. The initial value for can_pdate = true. The problem is, even if I change can_update to false (using disable_update function), in the update_groups function it still comes as true.

  const [can_update, set_can_update] = useState(true);
  const [groups, set_groups] = useState([]);

  const intervalRef = useRef();

  useEffect(() => {
    update_groups();
    const update_interval = setInterval(() => {
      update_groups();
    }, 33000);
    intervalRef.current = update_interval;
    return () => {
      clearInterval(intervalRef.current);
    };
  }, [project_data.id]);

  const update_groups = () => {
    if (can_update) {
      UI.get(`/project/${project_data.id}/controllers/`).then(
        (data) => {
          set_groups(data.groups);
        },
        (error) => {
          console.log("Не удалось загрузить список групп");
        },
      );
    }
  };

  const enable_update = () => {
    set_can_update(true);
  };

  const disable_update = () => {
    set_can_update(false);
  };

I've tried moving condition into

setInterval: `const update_interval = setInterval(() => {
    if (can_update){ update_groups()};
}

and replacing setInterval for recursive setTimeout. No changes.

I've had somewhat similar code inside a class component, and there didn't seem to be any problems like this.


Solution

  • You need add can_update to useEffect deps, otherwise

    all values from the component scope (such as props and state) that change over time and that are used by the effect. https://reactjs.org/docs/hooks-effect.html

    In your case useEffect was called once, inside it every 33 seconds a function update_groups was called with scoped value can_update = true.

    React.useEffect(() => {
        if (can_update) {
            update_groups();
            const update_interval = setInterval(() => {
                update_groups();
            }, 33000);
            intervalRef.current = update_interval;
            return () => {
                clearInterval(intervalRef.current);
            };
        }
    }, [project_data.id, can_update]);
    
    const update_groups = () => {
        UI.get(`/project/${project_data.id}/controllers/`).then(
            data => {
                set_groups(data.groups);
            },
            error => {
                console.log('Не удалось загрузить список групп');
            },
        );
    };