Upgrade to Pro — share decks privately, control downloads, hide ads and more …

State Management with MobX

State Management with MobX

React Bangkok 3.0.0

Transcript

  1. State management with MobX React Bangkok 3.0.0 - 24 June

    2018
  2. About Me • Manatsawin Hanmongkolchai • Junior Architect @ Wongnai

    ◦ We do everything from infrastructure to frontend
  3. Are you familiar with AngularJS?

  4. How state management worked in AngularJS (~2013)

  5. angular.controller('PageController', function($scope){ $scope.text = 'Hello world'; });

  6. angular.controller('PageController', function($scope, $http){ $scope.data = []; $http.get('/_api/restaurants.json') .then(function(response){ $scope.data =

    response.data; }); });
  7. angular.controller('PageController', function($scope, $http){ $scope.data = []; $http.get('/_api/restaurants.json') .then(function(response){ $scope.data =

    response.data; }); });
  8. angular.controller('PageController', function($scope, $http){ $scope.data = []; $http.get('/_api/restaurants.json') .then(function(response){ $scope.data =

    response.data; }); });
  9. angular.controller('PageController', function($scope, $http){ $scope.data = []; $http.get('/_api/restaurants.json') .then(function(response){ $scope.data =

    response.data; }); });
  10. angular.controller('PageController', function($scope, $http){ $scope.data = []; $http.get('/_api/restaurants.json') .then(function(response){ $scope.data =

    response.data; }); });
  11. How state management works with Redux Thunk

  12. Reducer Action State Action creator New state

  13. function fetchAction(){ return (dispatch) => { fetch('/_api/restaurants.json') .then((res) => res.json())

    .then((data) => dispatch({ type: 'SET_RESTAURANT', data })); }; }
  14. function reducer(state, action){ switch(action.type){ case 'SET_RESTAURANT': return Immutable.fromJS(action.data); default: return

    state || new Immutable.List(); } }
  15. Redux works, but... • It is quite boilerplatey ◦ Some

    people just give up and just use it as key value store • It has too many friends ◦ react-redux, immutablejs, redux-immutable, redux-thunk/saga ◦ Some people add reselect, redux-action • It is hard to get new people onboard ◦ Not only they have to learn React and Redux, they have to learn ALL of the above as well
  16. Redux works, but... • It has one store ◦ 75%

    of wongnai.com page content is Redux state. Why we have to send you empty delivery coupons store when you'll never look at it? ◦ We're working on it. Stay tuned on life.wongnai.com
  17. Introducing MobX

  18. MobX is a state management library

  19. If you used AngularJS, you'll feel at home with MobX

  20. ...without Dependency Injection, Factory, Controller, etc.

  21. MobX is a state management library

  22. Let's take a look at MobX, compared to AngularJS

  23. $scope.data = []; let scope = observable({ data: [] });

    $http.get('/_api/restaurants.json') .then(function(response){ $scope.data = response.data; }); fetch('/_api/restaurants.json') .then((res) => res.json()) .then(action((data) => { scope.data = data; })); AngularJS MobX
  24. $scope.data = []; let scope = observable({ data: [] });

    $http.get('/_api/restaurants.json') .then(function(response){ $scope.data = response.data; }); fetch('/_api/restaurants.json') .then((res) => res.json()) .then(action((data) => { scope.data = data; })); AngularJS MobX Put this where you used to put $scope.$apply
  25. <ul> <li ng-repeat="item in data" ng-bind="item.name"></li> </ul> observer((props) => {

    return <ul>{state.data.map((item, index) => ( <li key={index}>{item.name}</li> ))}</ul>; }); AngularJS MobX
  26. <ul> <li ng-repeat="item in data" ng-bind="item.name"></li> </ul> observer((props) => {

    return <ul>{state.data.map((item, index) => ( <li key={index}>{item.name}</li> ))}</ul>; }); AngularJS MobX Wrap your view with this HOC
  27. People often use decorators syntax (but it is optional)

  28. Decorator syntax @observer function(props){ return <ul>{state.data.map((item, index) => ( <li

    key={index}>{item.name}</li> ))}</ul>; }
  29. … is mostly the same as higher order function observer(function(props){

    return <ul>{state.data.map((item, index) => ( <li key={index}>{item.name}</li> ))}</ul>; })
  30. Free stuff with observer shouldComponentUpdate (Don't use PureComponent) Zero waste

    state update
  31. @observer function(props){ return <ul>{state.data.map((item, index) => ( <li key={index}>{item.name}</li> ))}</ul>;

    }
  32. @observer function(props){ return <ul>{state.data.map((item, index) => ( <li key={index}>{item.name}</li> ))}</ul>;

    } Only update when state.data is updated Not when state.otherField is updated
  33. The more observer the better

  34. let Item = observer((props) => <li>{props.item.name}</li>); let View = observer(()

    => ( <ul>{state.data.map((item, index) => ( <Item key={index} item={item} /> ))}</ul> ));
  35. let Item = observer((props) => <li>{props.item.name}</li>); let View = observer(()

    => ( <ul>{state.data.map((item, index) => ( <Item key={index} item={item} /> ))}</ul> )); Dereference things as late as possible <Item key={index} name={item.name} />
  36. let Item = observer((props) => <li>{props.item.name}</li>); let View = observer(()

    => ( <ul>{state.data.map((item, index) => ( <Item key={index} item={item} /> ))}</ul> )); Let MobX know that this component depends on item.name
  37. How do I layout my MobX store?

  38. You can do it any way you want! Here's what

    I use
  39. export default class Settings { @observable settings = { color1:

    '#82cef7', }; @observable saving = false; @observable error = null; @observable url = null; }
  40. export default class Settings { @observable settings = { color1:

    '#82cef7', }; @observable saving = false; @observable error = null; @observable url = null; } Just plain old OOP
  41. export default class Settings { async save(url){ let result =

    await this._post(url, { data: JSON.stringify(this.settings), }); runInAction('set url', () => { this.url = result.url; }); } }
  42. import BaseSettings from './base'; export default class AlertStore extends BaseSettings

    { @observable settings = { color1: '#82cef7', color2: '#ffffff', color3: '#ffffff', } // free save!! }
  43. There's a lot more to MobX mobx-state-tree, mobx-utils, custom observable

    etc.
  44. Wongnai is using MobX in new products (sorry can't talk

    about it yet)
  45. None
  46. #WongnaiIsHiring careers.wongnai.com (หนานี้ใช NextJS)

  47. Thank you! I'll be hanging around or @awkwin on Twitter

    Question?