Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

205
Views
Immutable update pattern in react for nested data

Redux specifies that "The key to updating nested data is that every level of nesting must be copied and updated appropriately."

// changing reference in top level
const newState = {...oldState}
newState.x.y.z = 10;
setState(newState)

// or updating reference in all levels
const newState = {...oldState}
newState.x = {...newState.x}
newState.x.y = {..newState.x.y}
newState.x.y.z = 10

Is this is same for react, can't find the documentation regarding this on react.

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Yes, you should apply this concept when updating your state in React also. If you don't, you can have issues with components not re-rendering when you update your state. Normally, React will rerender your component when your state changes, in both of your examples you're doing this, as you're creating a new object reference at the top-level which will cause React to rerender your component and any of its child components (ie: the children components also get rerender when the parent component rerenders). However, there is an exception to this. If you've memoized a component to help with efficiency using React.memo(), your memoized child component will only update when the props that it's passed change. If you are passing a child component an object that is nested within your original state, React won't rerender that component unless that object reference has changed. This could lead to issues if your memoized children components are trying to use state from your parent component.

For example:

const { useState, memo } = React;
const App = () => {
  const [state, setState] = useState({
    x: {
      y: {
        z: 0
      }
    }
  });
  
  const changeStateBad = () => {
    // Your first technique (can cause issues)
    const newState = {...state};
    newState.x.y.z += 1;
    setState(newState);
  }
  
  const changeStateGood = () => {
    // Your second technique for updating at all levels (just rewritten slightly)
    const newState = {
      ...state,
      x: {
        ...state.x,
        y: {
          ...state.x.y,
          z: state.x.y.z + 1
        }
      }
    };

    setState(newState);
  }
  
  return <div>
    <NumberDisplay x={state.x} />
    <br />
    <button onClick={changeStateGood}>Good update</button>
    <br />
    <button onClick={changeStateBad}>Bad update</button>
  </div>
}

// A memoized component that only rerenders when its props update
const NumberDisplay = memo(({x}) => {
  return <h1>{x.y.z}</h1>;
});

ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

about 4 years ago · Juan Pablo Isaza Report

0

data types in JS can be divided into primitive data types (eg. string, number) and non-primitive data types (eg. object),

primitive data types can not be modified (eg. using String.prototype.replace will always return a new instance of a string) while non-primitive data types can - and the reference pointing to that data will be "updated" as well (that's a big simplification, but executing eg. x.y = 2 will not create a new instance of x - instead the x will be keept the same in every place it's referenced),

which means to detect a change in the new version of the state (in a most performant way) it is required to create a new instance of an Object, Array (and other non-primitive data type representations)

// changing reference in top level
const newState = { ...oldState }

// changing nested reference
const newState = {
    ...oldState,
    x: {
        ...oldState.x,
        y: 2 // new "y" value
    }
}

// changing nested reference, another example
const newState = {
    ...oldState,
    x: {
        ...oldState.x,
        y: {
            ...oldState.x.y,
            z: 'test' // new "z" value
        }
    }
}

you can read more how change is detected on a basic level here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#comparing_objects

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!