setState Machine

setState Machine

What if your components' state was deterministic?
Learn about the implementation of State Machines to manage React Components' state - from the basics of Automata theory to autogenerated tests.

414db81dca21f468b4d7acd88172370c?s=128

Michele Bertoli

April 13, 2018
Tweet

Transcript

  1. setState Machine @MicheleBertoli

  2. I’m Michele, a React fanboy

  3. I work in Ads at Facebook and I build user

    interfaces
  4. State is hard

  5. Infinite Scroll • Attach an event handler to scroll •

    Check if the user scrolled > 90% • Fetch more data
  6. if (scrollPercentage > 0.9) { this.fetch() }

  7. if ( scrollPercentage > 0.9 && !this.state.isFetching ) { this.fetch()

    }
  8. {this.state.isFetching ? 'Loading...' : null}

  9. if (!data.hasMore) { this.detach() }

  10. {this.state.hasError ? 'Something went wrong' : null}

  11. {isEmpty ? (isFetching ? <h2>Loading...</h2> : <h2>Empty.</h2>) : <div style={{

    opacity: isFetching ? 0.5 : 1 }}> <Posts posts={posts} /> </div> } source: github.com/reactjs/redux
  12. Bottom-up • Focus on linear transitions • Hard to understand

    • Edge cases
  13. State Machine

  14. Automata Theory • Abstract machines • Deterministic finite automata •

    <Q, Σ, δ, q0, F>
  15. A B C α β

  16. SEMI NO-SEMI TOGGLE TOGGLE

  17. SEMI SPACE SEMI TAB NO-SEMI TAB NO-SEMI SPACE TOGGLE SEMI

    TOGGLE SEMI USE TAB USE TAB
  18. Statecharts

  19. “A visual formalism for complex systems.” David Harel, 1987

  20. Statecharts Extension of the conventional formalism of state machines and

    state diagrams
  21. Clustering

  22. C A B β β α

  23. β C A B α

  24. β C D

  25. Orthogonality

  26. A B C D

  27. Guards

  28. A B event [guard]

  29. Actions

  30. A B event / action

  31. A entry action1 exit action2, action3

  32. Workflow

  33. Statechart Event Actions

  34. “A statechart is a magic-box: you tell it what happened,

    and it tells you what to do.” Luca Matteis, 2018
  35. yarn add xstate

  36. xstate Functional, Stateless JS Finite State Machines and Statecharts

  37. entry removeSemicolons entry addSemicolons noSemi semi TOGGLE TOGGLE

  38. const prettyMachine = Machine({ initial: 'semi', states: { semi, noSemi,

    }, })
  39. const semi = { on: { TOGGLE: 'noSemi' }, onEntry:

    'addSemicolons', }
  40. const noSemi = { on: { TOGGLE: 'semi' }, onEntry:

    'removeSemicolons', }
  41. const { actions } = prettyMachine .transition('semi', 'TOGGLE') // =>

    ["removeSemicolons"]
  42. yarn add react-automata

  43. react-automata A state machine abstraction for React

  44. start entry attach listening SUCCESS [hasMore] ERROR / error SCROLL

    [scrollPercentage > 0.9] READY fetching entry fetch finish SUCCESS [!hasMore] entry detach
  45. withStatechart(statechart)(MyInfiniteScroll)

  46. start entry attach listening finish SUCCESS [!hasMore] SUCCESS [hasMore] ERROR

    / error SCROLL [scrollPercentage > 0.9] READY fetching entry fetch entry detach
  47. class MyInfiniteScroll extends React.Component { attach() {} // render() {}

    }
  48. attach() { this.element.addEventListener( 'scroll', this.handleScroll ) }

  49. start entry attach READY SUCCESS [hasMore] listening finish SUCCESS [!hasMore]

    ERROR / error SCROLL [scrollPercentage > 0.9] fetching entry fetch entry detach
  50. this.props.transition('READY')

  51. ERROR / error SUCCESS [!hasMore] SUCCESS [hasMore] entry fetch fetching

    READY start entry attach listening finish SCROLL [scrollPercentage > 0.9] entry detach
  52. class MyInfiniteScroll extends React.Component { attach() {} fetch() {} //

    render() {} }
  53. fetch() { const { transition } = this.props loadData() .then(data

    => transition('SUCCESS', data) .catch(() => transition('ERROR')) }
  54. Workflow

  55. React Automata Transition (evt, data) Action Methods

  56. withStatechart(statechart, { devTools: true })( MyInfiniteScroll )

  57. <Action show="fetch"> Loading… </Action>

  58. “The best testing strategy is not writing tests.” Michele Bertoli,

    2016
  59. testStatechart({ statechart }, MyInfiniteScroll)

  60. exports[`fetching`] = ` <div> Loading... </div> `;

  61. exports[`error`] = ` <div> Something went wrong </div> `;

  62. Benefits • Fewer bugs • Easy to understand • What

    vs when
  63. “2018 front-end trend prediction: Everybody's going to start using state

    machines for UIs.” Max Stoiber, 2018
  64. bit.ly/automata-calculator

  65. Takeaways • States > Transitions • Top-down • Read more

    papers
  66. Constructing the User Interface with Statecharts Ian Horrocks, 1998 bit.ly/statecharts-book

    Statecharts: A Visual Formalism for Complex Systems David Harel, 1987 bit.ly/statecharts-paper
  67. T @gandellinux @DavidKPiano @ryanflorence @mogsie

  68. @MicheleBertoli