Search code examples
reactjsinfinite-loopuse-effectuse-state

Do updating state of an object inside the useEffect() creates a new object?


import { useEffect, useState } from "react";

function CountSecrets() {
  const [secret, setSecret] = useState({ value: "", countSecrets: 0 });

  useEffect(() => {
    if (secret.value === 'secret') {
      setSecret(s => ({...s, countSecrets: s.countSecrets + 1}));    }
  }, [secret]);
  const onChange = ({ target }) => {
    setSecret(s => ({ ...s, value: target.value }));
  };

  return (
    <div>
      <input type="text" value={secret.value} onChange={onChange} />
      <div>Number of secrets: {secret.countSecrets}</div>
    </div>
  );
}

when the secret is typed the react goes into an infinite loop

I am reading this code through a blog post and its written that the setting the state of an object inside the useEffect creates a new object so the dependency inside the [ ] of useEffect changes and cause infinite loop.

Here is my question when we type and onchange is triggered and is also updating the state, so is updating the state inside the onchange do not creates a new object?And what are the cases of creation of new objects ?

Here is the link of the blog (its the second point) Link


Solution

  • Thumb rule in React is that state object is immutable, can not change it directly. So whenever you want to update state you always create new objects.

    Looking at your code, new objects created in both the cases in onChange as well as in useEffects. But useEffects creates infinite loop as dependency gets changed whereas onChange does not create infinite loop as state update does not onChange again

    if you want to avoid an infinite loop, I suggest 2 ways.

    • Change the dependency array from [secret] --> [secret.value]
    • Or have these 2 values value, countSecretsas 2 different state

    In summary, when you have object as state then you should always create new object and set it. Where as for value based state, react will take care of it.