optimizely / nuclear-js

Reactive Flux built with ImmutableJS data structures. Framework agnostic.
https://optimizely.github.io/nuclear-js/
MIT License
2.23k stars 141 forks source link

Observer not called #232

Closed mbinette closed 7 years ago

mbinette commented 7 years ago

This is one of my store methods. Everything in the state is correct after the call is finished. I have other code that observes the 'students' map. Even though I'm updating 'students', my observer doesn't get called if the 'counts' are not also changing. So if the two "mState.hasIn" lines return false so no update to 'counts' is done, the 'students' is updated but my observer on 'students' is not called.

If either of the "Mstate.hasIn" lines return true, and 'counts' is updated, my 'students' observer does get called. Am I missing something simple in how I'm using withMutations maybe?

function studentStatusChanged(state, {change, response}) {
  return state.withMutations(mState => {
    if (mState.hasIn(['counts', change.status])) mState.updateIn(['counts', change.status], total => total - 1);
    if (mState.hasIn(['counts', change.statusNew])) mState.updateIn(['counts', change.statusNew], total => total + 1);
    response.data.filter(event => event.aggregateType === "student").forEach(student => {
      mState.updateIn(['students', student.aggregateId], item => {
        item.status = student.data.status;
        item.version = student.version;
        return item;
      });
    });
  })
}

When the observer is NOT called I can simply refresh my view and see the new state correctly or evaluate the path in the console and see that the state has been modified.

mbinette commented 7 years ago

As additional information, it seems to be an issue with the updateIn call. The item that is returned is a reference to the original item in state which means it really isn't changing according to Nuclear. I have to figure out how to update a couple different properties within item and have it be a different object.

mbinette commented 7 years ago

The final solution was to use

      mState.updateIn(['students', student.aggregateId], item => {
        let newItem = Object.assign({}, item);
        newItem.status = student.data.status;
        newItem.version = student.version;
        return newItem;
      });

This isn't an issue with Nuclear but with how I was using ImmutableJS.