wisha
wisha

Reputation: 713

Are React useEffect hooks guaranteed to execute in order?

Let's say I have this:

function Example(props) {
  const { prop1, prop2 } = props;
  const latestProp1 = useRef(prop1);

  useEffect(() => {
    latestProp1.current = prop1;
  }, [prop1]);

  useEffect(() => {
    console.log(latestProp1.current);
  }, [prop2]);

  return null;
}

If both prop1 and prop2 change in the same re-render, is it guaranteed that the console would log the new prop1 value?

And if I swap the useEffect hooks' position -

  useEffect(() => {
    console.log(latestProp1.current);
  }, [prop2]);

  useEffect(() => {
    latestProp1.current = prop1;
  }, [prop1]);

would it be guaranteed that the console would log the old prop1 value (from before the render)?

Upvotes: 10

Views: 5270

Answers (1)

Dennis Vash
Dennis Vash

Reputation: 53944

Yes, if you follow the Rules of Hooks, the call order ensured (hooks are called via array index, check how hooks implemented).

By following this rule, you ensure that Hooks are called in the same order each time a component renders.

Therefore, by simulating a batched set state (both prop1 and prop2 change in the same re-render) you can notice that first will always be logged before second:

function Example(props) {
  const { prop1, prop2 } = props;

  React.useEffect(() => {
    console.log("first");
  }, [prop1]);

  React.useEffect(() => {
    console.log("second");
  }, [prop2]);

  return <>Example</>;
}

function Component() {
  const [counter, setCounter] = React.useState(0);
  const [counter2, setCounter2] = React.useState(0);

  const together = () => {
    setCounter2((p) => p + 1);
    setCounter((p) => p + 1);
  };

  return (
    <>
      <Example prop1={counter} prop2={counter2} />
      <button onClick={together}>together</button>
    </>
  );
}

Edit Example Batching Call Order

Upvotes: 9

Related Questions