10

Let's stay I have this myObject loaded via an API call:

myObject = {
  fieldA: { details: 'OK', message: 'HELLO' },
  fieldB: { details: 'NOT_OK', message: 'ERROR' },
}

Only details and message of each field can change. I want this object to be observable in a MobX store (which properties? to be defined below). I have a simple React component which reads the two fields from the store:

@observer
class App extends Component {
  store = new Store();

  componentWillMount() {
    this.store.load();
  }

  render() {
    return (
      <div>
        {this.store.fieldA && <p>{this.store.fieldA.details}</p>}
        {this.store.fieldB && <p>{this.store.fieldB.details}</p>}
      </div>
    );
  }
}

I read this page trying to understand what MobX reacts to, but still didn't get a clear idea. Specifically, which of the 4 stores below would work, and why?

1/

class Store1 = {
  @observable myObject = {};

  @action setMyObject = object => {
    this.myObject = object;
  }

  load = () => someAsyncStuff().then(this.setMyObject);
}

2/

class Store2 = {
  @observable myObject = {};

  @action setMyObject = object => {
    this.myObject.fieldA = object.fieldA;
    this.myObject.fieldB = object.fieldB;
  }

  load = () => someAsyncStuff().then(this.setMyObject);
}

3/

class Store3 = {
  @observable myObject = { fieldA: {}, fieldB: {} };

  @action setMyObject = object => {
    this.myObject = object;
  }

  load = () => someAsyncStuff().then(this.setMyObject);
}

4/

class Store4 = {
  @observable myObject = { fieldA: {}, fieldB: {} };

  @action setMyObject = object => {
    this.myObject.fieldA = object.fieldA;
    this.myObject.fieldB = object.fieldB;
  }

  load = () => someAsyncStuff().then(this.setMyObject);
}
Brian Burns
  • 14,953
  • 5
  • 69
  • 59
jeanpaul62
  • 6,379
  • 6
  • 40
  • 74

1 Answers1

8

All of the above will work, except for solution 2. That because as described in Mobx docs about objects:

When passing objects through observable, only the properties that exist at the time of making the object observable will be observable. Properties that are added to the object at a later time won't become observable, unless extendObservable is used.

In the first solution you re-assign the object again with the properties already exist in the returned object. In 3 and 4 you initialized the object with those 2 properties so it works.

Also I think in your component example you meant to use it like this (otherwise, it won't work in any way):

render() {
    const { myObject } = this.store;

    return (
      <div>
        {myObject && myObject.fieldA && <p>{myObject.fieldA.details}</p>}
        {myObject && myObject.fieldB && <p>{myObject.fieldB.details}</p>}
      </div>
    );
}
Doron Brikman
  • 2,176
  • 1
  • 12
  • 14