Updating An Object in React

To update an object and its nested objects, make a copy of the original state with object spread, which then can be modified.

January 18, 2022 | Not my art.

The copy can then be set to replace the original state. This approach is necessary because React does not merge states when they are updated. React centers around immutability.

For my patient data management application, I have an object whose structure is the following:

const initialStateBelow61 = {
  sodium: { min: 136, max: 145 },
  potassium: { min: 3.5, max: 5.1 },
  carbonDioxide: { min: 23, max: 29 },
  chloride: { min: 98, max: 107 },
  glucose: { min: 70, max: 99 },
  calcium: { min: 8.6, max: 10.2 },
  bloodUreaNitrogen: {
    min: 6,
    max: 20,
  },
  creatinineMen: {
    min: 0.9,
    max: 1.3,
  },
  creatinineWomen: {
    min: 0.6,
    max: 1.1,
  },
};

...

const initialState = {
  below61: initialStateBelow61,
  over60: initialStateRefDataOver60,
  over90: initialStateRefDataOver90,
};

const [refData, setRefData] = useState(initialStateBelow61);

These values are the reference ranges for adults younger than 61 in a Basic Metabolic Panel report.

I am adding the functionality that allows the user to use these default values for generating patient reports, or set new ones. For each min and max value is a corresponding input field. The goal is to update the min or max value only, per input field without changing other values.

The input fields’ onChange event handlers will call setRefDataHandlerBelow61.

<Input
  className="input-element"
  type="number"
  name="sodium"
  value={refData.below61.sodium.max}
  onChange={(e) =>
    setRefDataHandlerBelow61(
      e.target.name,
      refData.below61.sodium.min,
      e.target.valueAsNumber
    )
  }
  required={true}
  placeholder="0"
/>

To update the states, setRefData creates a copy of the entire refData using the object spread ... so that all other objects inside it stay unchanged. Then we target the nested object we want to change below61 within refData. Inside the next nested object we make another copy, this time of refData.below61 . The values we actually want to change are targeted using [testName]: { min, max }.

const setRefDataHandlerBelow61 = (
  testName: string,
  min: number,
  max: number
) => {
  if (min === 0 || max === 0) {
    return;
  }
  setRefData({
    ...refData,
    below61: { ...refData.below61, [testName]: { min, max } },
  });
};