Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

React state management with Redux and MobX

1,158 views

Published on

The presentation for the Shift Split 2017 conf workshop.
Example project repo: https://github.com/infinum/shift-2017

Published in: Technology
  • Be the first to comment

React state management with Redux and MobX

  1. 1. React State Management with Redux and MobX DARKO KUKOVEC @DarkoKukovec ANDREI ZVONIMIR CRNKOVIĆ @andreicek INFINUM @infinumco
  2. 2. DARKO KUKOVEC JS Team Lead @DarkoKukovec ANDREI ZVONIMIR CRNKOVIĆ JS Emojineer @andreicek
  3. 3. We're an independent design & development agency.
  4. 4. Topic Time SCHEDULE 13:45-14:30 14:30-15:15 15:15-16:00 React setState React + Redux React + MobX The Joy of Optimizing Una Kravets (DigitalOcean) Coffee.js? How I hacked my coffee machine using JavaScript Dominik Kundel (Twilio) GraphQL: Data in modern times Dotan Simha (The Guild)
  5. 5. 01APP STATE
  6. 6. APP STATE • Data • Which user is logged in? • Which todos did the user create? • UI • Which todos is the user looking at (filter - all, complete, incomplete)
  7. 7. 02STATE MANAGEMENT
  8. 8. STATE MANAGEMENT • What should happen when some data changes? • Does the UI need to be updated • Does some other data depend on it? • Does the app need to make an action (e.g. API call)?
  9. 9. 03WHY DO WE NEED IT?
  10. 10. IMAGE GOES INSIDE THIS BOX DELETE BOX AFTER PLACING IMAGE
  11. 11. • Todos • Title • Status • Active filter • Number of todos
  12. 12. Handing an action in the app
  13. 13. Handing an action in the app • The user checks a todo as complete
  14. 14. Handing an action in the app • The user checks a todo as complete • Mark the todo as complete
  15. 15. Handing an action in the app • The user checks a todo as complete • Mark the todo as complete • Update the incomplete items count
  16. 16. Handing an action in the app • The user checks a todo as complete • Mark the todo as complete • Update the incomplete items count • What filter is active again?
  17. 17. Handing an action in the app • The user checks a todo as complete • Mark the todo as complete • Update the incomplete items count • What filter is active again? • Do I need to update the list of todos? • Add/remove item? • Sort items? • Should I show an empty state? • Should I make an API call? • Should I save the change into localStorage?
  18. 18. Data Flow in JavaScript Applications - Ryan Christiani
  19. 19. 04EXAMPLE PROJECT
  20. 20. EXAMPLE PROJECT • Tech conference app • Fetch talk list (async action) • Favourite talks (simple sync action) • Filter by location (filtering data from the state) • To simplify • No routing • No forms • Not responsive • Only basic styling • Assumption: Browsers support Fetch API • 70% of browsers do, polyfill available for the rest
  21. 21. EXAMPLE PROJECT - TECH STUFF • create-react-app as the initial setup • https://github.com/infinum/shift-2017
  22. 22. 05BEFORE WE START...
  23. 23. COMPONENT TYPES Container Presenter Usually root components Inside of container components No UI Only UI State of children components Dumb component Handle state changes "Data down, actions up"
  24. 24. 06PREREQUISITES
  25. 25. PREREQUISITES • A modern IDE (VS Code, Sublime Text, Atom, Webstorm or similar) • Latest version of Chrome/Chromium for debugging • Node.js 6 or 7 • npm 4 or yarn
  26. 26. 07REACT + SETSTATE
  27. 27. REACT + SETSTATE • No central state • Every component contains its (and children?) state • State changes are async! - 2nd argument is a callback • Component is re-rendered unless shouldComponentUpdate() returns false • Additional libs • react-addons-update
  28. 28. // Code time! // setState // Code used for setup: create-react-app app-setstate npm install --save react-addons-update v1.0
  29. 29. * Mock data * Styles * Presenter components * Utils v1.0
  30. 30. // Loading data v1.0
  31. 31. // Container component state v1.1
  32. 32. // Selectors v1.2
  33. 33. FUNCTIONAL SETSTATE • Since React 15? • Will eventually replace the usage with objects as the first argument
  34. 34. class App extends Component { constructor(props) { super(props); this.state = {counter: 0}; } increaseCounter() { this.setState({ counter: this.state.counter + 1 }); } decreaseCounter() { this.setState((prevState, props) => { return {counter: prevState.counter + 1}; }); } render() { // ... } }
  35. 35. SCALING SETSTATE • A bad idea • One master component with app state • Some smaller independent containers
  36. 36. 08MOBX VS REDUX
  37. 37. http:!//!!www.timqian.com/star-history/#mobxjs/mobx&reactjs/redux&facebook/flux&facebook/relay
  38. 38. ADVANTAGES Easier to (unit) test MobX Redux Faster Less boilerplate Smaller Time travelMore flexible Easier to debug?Simpler async actions
  39. 39. IN THE NUTSHELL... https:!//twitter.com/phillip_webb/status/705909774001377280
  40. 40. USAGE MobX Redux mobx-react react-redux Not React dependent Not React dependent mobx-angular Python GWT
  41. 41. 09REACT + REDUX
  42. 42. REACT + REDUX • One central state • Additional libs • redux • react-redux • redux-thunk
  43. 43. STORE Holds application state
  44. 44. ACTIONS Payloads of information that send data from your application to your store
  45. 45. REDUCERS Specify how the application's state changes in response to actions
  46. 46. import { createStore } from 'redux' function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } } let store = createStore(counter) store.subscribe(() => console.log(store.getState()) ) store.dispatch({ type: 'INCREMENT' }) // 1 store.dispatch({ type: 'INCREMENT' }) // 2 store.dispatch({ type: 'DECREMENT' }) // 1 THE GIST
  47. 47. // Code time! // Redux // Code used for setup: create-react-app app-redux npm install --save redux react-redux redux-thunk v2.0
  48. 48. * Mock data * Styles * Presenter components * Utils v2.0
  49. 49. // Action names v2.0
  50. 50. // Actions v2.1
  51. 51. // Reducers v2.2
  52. 52. // Store v2.3
  53. 53. // Connect v2.4
  54. 54. // Selectors v2.5
  55. 55. // Redux DevTools // https://chrome.google.com/webstore https:!//chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en v2.6
  56. 56. SCALING REDUX • Only one store! • Multiple (nested) reducers, actions • Store data nesting === reducer nesting • "reducers" folder, "actions" folder • Folders based on functionality • e.g. "orders" contains a orders reducer, orders actions and all other related stuff
  57. 57. THINGS TO KEEP IN MIND • NEVER mutate the state! • Immutable.js
  58. 58. 09REDUX HELPER LIBS
  59. 59. IMMUTABLE.JS • https://github.com/facebook/immutable-js/ • List, Stack, Map, OrderedMap, Set, OrderedSet, Record • Nested structures
  60. 60. REDUX FORM • https://github.com/erikras/redux-form • Uses Immutable.js • Sync/async validations • Wizard forms
  61. 61. REDUX - THE SOURCE CODE https:!//twitter.com/bloodyowl/status/740228059538857984
  62. 62. 10REACT + MOBX
  63. 63. REACT + MOBX • One/multiple states • Additional libs • mobx • mobx-react
  64. 64. Anything that can be derived from the application state, should be derived. Automatically. - The philosophy behind MobX
  65. 65. OBSERVABLE Your state e.g., list of TODOs
  66. 66. ACTION A function that changes the state e.g., function called after the user clicks on the completed checkbox
  67. 67. COMPUTED PROPERTY A value derived from your state e.g., list of completed TODOs
  68. 68. OBSERVER Function (component?) that needs to be updated on state change e.g., component showing a list of TODOs
  69. 69. STATE (OBSERVABLES) COMPUTED PROPS OBSERVERSACTION UPDATES UPDATES UPDATES CHANGES
  70. 70. THE GIST import { observable, autorun } from 'mobx'; const store = observable({counter: 0}); autorun(() => console.log(store.counter); ); store.counter++; // 1 store.counter++; // 2 store.counter--; // 1
  71. 71. import { createStore } from 'redux' function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } } let store = createStore(counter) store.subscribe(() => console.log(store.getState()) ) store.dispatch({ type: 'INCREMENT' }) // 1 store.dispatch({ type: 'INCREMENT' }) // 2 store.dispatch({ type: 'DECREMENT' }) // 1 THE GIST import { observable, autorun } from 'mobx'; const store = observable({counter: 0}); autorun(() => console.log(store.counter); ); store.counter++; // 1 store.counter++; // 2 store.counter--; // 1 MobX Redux
  72. 72. DECORATORS JS proposed feature (Babel plugin) TypeScript feature
  73. 73. import {observable, computed} from 'mobx'; class Todos { @observable list = []; users = observable([]); @computed get complete() { return this.list.filter((todo) => todo.complete); } incomplete: computed(() => { return this.list.filter((todo) => !todo.complete); }) }
  74. 74. // Code time! // MobX // Code used for setup: create-react-app app-mobx --scripts-version custom-react-scripts npm install --save mobx mobx-react v3.0
  75. 75. * Mock data * Styles * Presenter components * Utils v3.0
  76. 76. // Models v3.0
  77. 77. // Loading data v3.1
  78. 78. // Actions v3.2
  79. 79. // Observers v3.3
  80. 80. // Strict mode v3.4
  81. 81. THINGS TO KEEP IN MIND • use extendObservable to add properties to an object • Wrapped objects - isArray(arr) or array.is(toJS(arr)) • Don't be afraid to use observers • If done right: More observers → better performance
  82. 82. SCALING MOBX • Your code can be object oriented! • A list of best practices • Strict mode, actions (transactions) • Use helper libs
  83. 83. 10MOBX HELPER LIBS
  84. 84. MOBX-REACT-DEVTOOLS • Log actions & reactions • Check dependencies for a react component • Show update times
  85. 85. "STRUCTURE" LIBS Opinionated
  86. 86. MOBX-COLLECTION-STORE • https://github.com/infinum/mobx-collection-store • One collection, multiple model types • Relationships between models • mobx-jsonapi-store • https://github.com/infinum/mobx-jsonapi-store
  87. 87. MOBX-STATE-TREE • https://github.com/mobxjs/mobx-state-tree • Made by MobX authors • v1.0 release soon • Supports snapshots, replay, JSON patches, etc. • Supports time travel! • Compatible with Redux DevTools!
  88. 88. MOBX-REACT-FORM • https://github.com/foxhound87/mobx-react-form • Dedicated DevTools: https://github.com/foxhound87/mobx-react-form-devtools
  89. 89. REACT SETSTATE + MOBX • You can still use it • But, you can also do this…
  90. 90. import {observable} from 'mobx'; import {observer} from 'mobx-react'; import React, {Component} from 'react'; @observer export default class Foo extends Component { @observable state = { clickCount = 0; }; onClick: () => { this.state.clickCount++; // if you use setState it will stop being an observable! } render() { return ( <button onClick={this.onClick}> { this.state.clickCount ? `Clicked ${this.state.clickCount} times!` : 'Click me!' } </button> ); } }
  91. 91. RESOURCES • Redux • http://redux.js.org/ • https://egghead.io/courses/getting-started-with-redux • https://egghead.io/courses/building-react-applications-with-idiomatic-redux • MobX • https://mobx.js.org/ • https://mobxjs.github.io/mobx/getting-started.html • https://egghead.io/courses/manage-complex-state-in-react-apps-with-mobx
  92. 92. Visit infinum.co or find us on social networks: infinum.co infinumco infinumco infinum Thank you! DARKO@INFINUM.CO @DARKOKUKOVEC ANDREI@INFINUM.CO @ANDREICEK

×