Yuval Adam
Yuval Adam

Reputation: 165242

Triggering a React effect periodically

Consider the following simple React component with an effect that fetches some data and saves it to the component state:

function MyComponent(props) {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch("data.json");
      setData(await res.json());
    };
    fetchData();
  }, []);

  return (
    <></>
  )
}

What is the right way to set this effect to run periodically, say every minute?

Is it as easy as replacing fetchData() with setInterval(fetchData, 60) or are there other React-specific considerations I should be thinking of?

Upvotes: 3

Views: 736

Answers (2)

Dennis Vash
Dennis Vash

Reputation: 53884

Are there other React-specific considerations I should be thinking of?

Just for the completeness of Joseph's answer, you should consider memoizing the component's children, or it will rerender them on each interval:

//                         v Notice the children
function MyComponent({ children }) {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch('data.json');
      setData(await res.json());
    };

    const interval = setInterval(fetchData, 60000);

    return () => clearInterval(interval);
  }, []);


//            v Causes children to re-render every interval
  return <>{children}</>;
}
export default MyComponent;

Possible case:

<MyComponent>
  <Child />
</MyComponent>

Solution:

// Possible Child
function Child = () => <></>

//                     v Memoization using shallow comparison
export default React.memo(Child);

Upvotes: 2

Joseph D.
Joseph D.

Reputation: 12174

Is it as easy as replacing fetchData() with setInterval(fetchData, 60)

Yes.

Just make sure to do clearInterval (return of useEffect()) when component unmounts.

useEffect(() => {
  const fetchData = async () => {
    const res = await fetch("data.json");
    setData(await res.json());
  };

  const t = setInterval(fetchData, 60000);

  return () => clearInterval(t); // clear
}, []);

Upvotes: 5

Related Questions