Search code examples
reactjsreact-hooksrerender

React does not trigger rerender if you assign state value to another variable and then change the state


I stumbled upon a strange behaviour due to my lack of knowledge and experience. I have a Component called inside another, looking like this:

            <CustomSelectionButtons
              values={roleTypes}
              label="Roles:"
              onSelect={setUserRoles}
              selected={roles}
            />

roles is a state variable, which is set with the onSelect method (setUserRoles). Here it is:

  const setUserRoles = (button: AccountsAndRolesUnion) => {
   const updatedRoles: AccountsAndRolesUnion[] = roles; //this is the state variable.

   /* doing something with the local **updatedRoles** array */

   setRoles(updatedRoles);
  };

If I use the code like this, the component does not rerender after setRoles hook call. However, If I assign the local variable with roles.slice(), everything works as expected, the component is rerendered. So, this works:

const setUserRoles = (button: AccountsAndRolesUnion) => {
  const updatedRoles: AccountsAndRolesUnion[] = roles.slice(); //slicing the state variable.

  /* doing something with the local **updatedRoles** array */

  setRoles(updatedRoles);
};

Can someone explain why this happens?


Solution

  • Slice creates a shallow copy of the original array, meaning that it returns a different object than roles itself, even though its content may be the same.

    When you do setRoles(roles), you are actually sending the exact same object in memory, and when React compares the props before deciding whether to re-render, it doesn't detect any difference. However, when you do setRoles(roles.slice()), you pass a different variable in memory, so React figures there is a change in props and re-renders.