1

I have a pimRegistration state initialization as shown in the chrome redux-devtools screen capture below. The nesting being referenced is pimRegistration (state.domain.patient):

enter image description here

I updated the patient.name object with the following spread operator statement:

store.update((state) => ({
  ...state,
  ...patientPath,
  ...{ [property]: value },
}));

...where property is the "name" property of the patient object with value. After the update, the following screenshot shows the new state:

New updated state - yellow colour in screenshot

Note that the original patient object (purple in the screenshot) is updated with the name object, duplicated and placed at the root of the state (yellow in screenshot).

I would like to overwrite the properties of the pimRegistration(state).domain.patient object, not to create a new patient object.

The state update is called as shown below.

store.update((state) => ({
  ...state,
  ...patientPath, // state.domain.patient
  ...{ [property]: value },
}));

I have tried my different combinations without achieving the desired result.


The complete update function is shown below.

update(property: string, path: string, value: any) {
  const paths: string[] = path.split(".");

  const pathReducer = (state: IRegistrationState, path_: string) => {
    if (paths.length <= 0) {
      return state.domain;
    }
    return state[path_];
  };

  const domainPath = state.domain;
  let patientPath, nokPath, referrerPath;

  if (path.includes("patient")) {
    patientPath = paths.reduce(pathReducer, state);
  }

  if (path.includes("nok")) {
    nokPath = paths.reduce(pathReducer, state);
  }

  if (path.includes("referrer")) {
    referrerPath = paths.reduce(pathReducer, state);
  }

  store.update((state) => ({
    ...state,
    ...patientPath,
    ...{ [property]: value },
  }));
}

The function above is invoked with the following statement in Angular 2.

if (this.path.includes("patient")) {
  this._repo.update("name", "domain.patient", this.name);
}

Thanks

OFRBG
  • 1,653
  • 14
  • 28
st_clair_clarke
  • 5,453
  • 13
  • 49
  • 75
  • What is `patientPath`? You may be treating object spreading as if it merged properties. It does _not_ merge recursively. – OFRBG Feb 27 '22 at 21:27
  • I updated/appended the question to show the complete state updater function and function invokation above. Thanks. – st_clair_clarke Feb 27 '22 at 21:33

1 Answers1

1

Deep updates to a store can be tricky. In your function you seem to be spreading the updates at the root rather than at the level you want the update at. This answer here outlines the usual practice to update the state. In short, something like

const newState = {
  ...state,
  domain: {
    ...state.domain,
    patient: {
      ...state.domain.patient,
      [property]: value
    }
  }
}

Dynamically passing a path and updating this state can be… cumbersome. There are libraries that can help you do it such as immer, but you can possibly hack your way around with normal JS/TS.

OFRBG
  • 1,653
  • 14
  • 28
  • As far as I remember, in redux it's also possible to split the state into different sub-states and and have a reducer per a sub-state. These portions can then be merged into single object. – E. Shcherbo Feb 27 '22 at 22:06
  • @E.Shcherbo that's true. I'm not sure if OP is open to refactoring into pseudo-slices, but that's certainly an option. – OFRBG Feb 27 '22 at 22:36