U.Rush
U.Rush

Reputation: 458

When 'action'/'runInAction' is really needed in mobx react

Can someone explain to me what is the real difference and why both of the example here are working the same:

1) Change a state of observable via action/runInAction inside the store file:

colorStore file:

@observable
color='red'

@action
setColor(){
  this.color='blue'
}

2)Change the state via the component itself (which assumed to be bad practice):

React Component file:

onClick = () => this.props.colorStore.color='blue' //still working...

Upvotes: 6

Views: 3074

Answers (2)

Ivan V.
Ivan V.

Reputation: 8081

Mobx action is doing the batching, similarly to how ReactJS batches multiple changes.

When you use reactjs click handler react is automatically batching changes that happen inside it, so you will not see component rendering multiple times, however, if you call setColor from some other event, let's say after loading some data, and have multiple calls to change the observable inside the setColor that will trigger the observer three times, and the component will be rendered three times.

When you wrap your function with @action decorator or you use runInAction function, only the last value will be used (green in the code below) and the component will be rendered only once.

setColor(){
  // this will render three times
  this.color='blue'
  this.color='red'
  this.color='green'
}

vanilla mobx example that reacts only once:

import { runInAction, observable, reaction, toJS } from "mobx";

const test = observable({
  name: "sonic",
  nick: "speed demon"
});

// console.log will be called only once with the value "name: 3"
reaction(
  () => toJS(test),
  data => console.log(`name: ${data.name}`)
);

runInAction(() => {
  test.name = "1";
  test.name = "2";
  test.name = "3";
});

view on codesandbox

Also check out the discussion on the github repo: is @action really necessary?

Upvotes: 9

Antoan Elenkov
Antoan Elenkov

Reputation: 781

The difference is more related to conventions and writing clean maintainable code than in the behavior of the program. So:

  1. You are mutating store data in your UI component. This is not correct, because the UI should only visualize data and handle for example user actions which are then translated to certain action in the data store(in your case updating a color). It's store responsibility to manage the state of this data
  2. All observable data is considered a good practice to be mutated only in actions. Why? Because the single source of mutating data is clear - only in actions and only in a data layer(the store). The code is less prone to errors and unclear state management and the great benefit is that you can enforce your application not to build if you turn on use strict mode

Upvotes: 0

Related Questions