Home > Enterprise >  React useState rerender even if i pass the same reference?
React useState rerender even if i pass the same reference?

Time:06-22

What I know is that useState will not rerender if we pass the same state, and I test it by myself, but it worked only the first time the component rerendered, with an initial state passed to useState. But in the example below, the useState rerenders the component even if I pass the same reference, also useEffect knows that the state does not changed. The picture with console.logs shows that behavior.

const arr = [
  { name: 'Khaled', id: 0 },
  { name: 'Mohamed', id: 1 },
  { name: 'Ahmed', id: 2 },
  { name: 'Mohsen', id: 3 },
];

function App() {
  console.log('num $1');

  const [same, setSame] = useState({});

  useEffect(() => {
    console.log('num $3');

    const test = arr.find((el) => el.id === 0);
    console.log(Object.is(same, test));
    setSame(test);
  }, [same]);

  console.log('num $2');

  return <div>welcome</div>;
}

enter image description here

CodePudding user response:

The component is rendered twice because you have the initial value for the same state which is empty { }. inside the useEffect you update this state with a new object then the useEffect triggers a new value that has been added to the same state. which is the matched object from your array. then the component re-rendered and that's why you got in the console.log the true value.

   const arr = [
      { name: 'Khaled', id: 0 },
      { name: 'Mohamed', id: 1 },
      { name: 'Ahmed', id: 2 },
      { name: 'Mohsen', id: 3 },
    ];
    
    function App() {
      console.log('num $1');
    
      const [same, setSame] = useState({}); <= initial value
    
      useEffect(() => {
        console.log('num $3');
    
        const test = arr.find((el) => el.id === 0);
        console.log(Object.is(same, test)); <= changed from false to true because the new value of same
        setSame(test); <= you updated the state
      }, [same]); <= the value of same changed from { } to a new value and that's make the component to re-render
    
      console.log('num $2');
    
      return <div>welcome</div>;
    }

CodePudding user response:

Previous answer explains it perfectly. To not have the state re-render you must initialize it with the original array.

const arr = [
  { name: 'Khaled', id: 0 },
  { name: 'Mohamed', id: 1 },
  { name: 'Ahmed', id: 2 },
  { name: 'Mohsen', id: 3 },
];

function App() {
  console.log('num $1');

  const [same, setSame] = useState(arr); <= initial value is now original arr

  useEffect(() => {
    console.log('num $3');

    const test = arr.find((el) => el.id === 0);
    console.log(Object.is(same, test)); <= changed from false to true because the new value of same
    setSame(test); <= you updated the state
  }, [same]); <= the value of same changed from { } to a new value

  console.log('num $2');

  return <div>welcome</div>;
}

Make note that this only works for the reference types. Hook doesn’t perform a comparison on objects or arrays, it simply checks whether the reference changes or not. This does not work for value types.

  • Related