Mobx: How to observer a big Object?

Created on 28 Mar 2018  路  5Comments  路  Source: mobxjs/mobx

I'm working on a online live project.
when init the live room, I get a big Object from the server side.
roomData: { userMap: {}, anchorMap: {}, userList: [], activity: {}, roomId: ***, poster: '*****' }
Almost 30 properties . Most of the them are immutable, such as 'roomId'.
I've no idea how to use @observable.
@observable roomData or split 'roomData' ?

Most helpful comment

@megaboy101

Bonus pro tip: To save you some of the keystrokes

@action updateAsset = (newObj) => Object.assign(this, newObj)

All 5 comments

Per the Mobx docs;

Observable Objects

If a plain JavaScript object is passed to observable all properties inside will be copied into a clone and made observable. (A plain object is an object that wasn't created using a constructor function / but has Object as its prototype, or no prototype at all.) observable is by default applied recursively, so if one of the encountered values is an object or array, that value will be passed through observable as well.

In other words, you are completely safe to make the entire object observable. Mobx will recursively, in turn, make all the properties inside that object observable as well, but it's extremely efficient at doing this, so there's performance isn't a considerable issue.

Now, whether or not you want to actually store all your data under one property is another issue, and that ultimately comes down to personal necessity.
If you choose to keep everything together under one property you will be doing this a lot:

this.props.myClass.roomData.roomId;

As opposed to if you chose to split them up into their own individual properties:

this.props.myClass.roomId;

If you need more info regarding observables or Mobx in general the 10-minute interactive introduction is the best place to start, or the official docs

I have a very similar question as the original.

I am currently converting a project from very old react and jQuery to modern stack. We work on a vehicle monitoring site where the view is updated with new data as vehicles move.

Whenever vehicles moves or the sensor data changes, the server returns a large object containing all the vehicle information (including unchanged values). This is checked every few seconds.

as per the docs:

Domain objects

Each domain object should be expressed using its own class (or constructor function). It is recommended to store your data in denormalized form.

Reading that I am unsure as to how to create and update the observables when the vehicle updates currently from my understanding the options that I approaches that I have are:

1. Assign as object and update the complete Asset

With this approach as far as I can tell all observers of the asset will be rerendered as a completely new object will be generated and as such even unchanged values will be rerendered.

class Asset { 
  @observable asset = obj; 

  @action updateAsset = (newObj) => {
    this.asset = newObj;
  };

2. Observe the properties of the Asset

With this approach it is more work to create and update the asset but it will only render the specific properties that are changed.

class Asset { 
  @observable speed = 0; 
  @observable latitude = null; 
  @observable longitude = null; 
  .... etc

  @action updateAsset = (newObj) => {
    this.speed = newObj.speed;
    this.latitude = newObj.latitude;
    this.longitude = newObj.longitude;
    .... etc
  };

What a coincidence, a lot of the work I'm doing right now involves a very similar scenario to yours! Ultimately the decision should come down to whatever is easier for you, but my recommendation would be to go with the second option, i.e. modeling the Mobx object after the actual data it's being derived from. There are many advantages to this approach, and I think this article sums it up very well.

You may also want to check out GraphQL, it definetly isn't a trivial endeavor but it may help you handle this sort of data fetching and updating routine much more efficiently. In situations like this instead of having to send an entire object every time a single property updates, you would only need to send the actaully updating properties. There is an excellent set of free tutorials you can check out here if you're interested, the first few will give you a high level idea of if it's something worth your time.

Bonus pro tip: To save you some of the keystrokes of mapping all of those input object properties to your Mobx properties, you can use this snippet to do it for you:

@action updateAsset = (newObj) => {
  for (let prop in newObj) {`
    this[prop] = newObj[prop];
  }
}

@megaboy101

Bonus pro tip: To save you some of the keystrokes

@action updateAsset = (newObj) => Object.assign(this, newObj)

Closing as question seems answered

Was this page helpful?
0 / 5 - 0 ratings