State Management in React with Chance Strickland

InstructorJoel Hooks

Share this video with your friends

Send Tweet

Joel and Chance chat about the big ideas of State Management and when you should start implementing a State Machine in your application. Chance gives a walkthrough of how Reach UI handles State, how the Listbox component was built, and how reading the React UI source code is an excellent source of learning material.

Resources:

Reach UI

What are the big ideas of State Management?

  • A good starting point is understanding why React is so popular. React gave us a very convenient way of thinking about our application based on State. It determined that you're UI is a function of your State.
    • That was a simple and revolutionary idea that changed how we manage the State.
    • Tools like Redux and Flux have helped us think about State at a higher level.
  • State should be managed closer to the components. The closer you can keep the State to where things are happing, the more deterministic.
  • Reach UI - uses a State Machine model.

When should you add a State Machine?

  • It's essential to understand what a State Machine is first. A finite-state machine is a mathematical model of computation. You will only have one State at any given time.
  • First, you would define your States and then integrate events.
  • You always want to think like a finite-state machine when building a new component.
    • Once you start thinking in those terms, you start writing your code differently. An example of this is Boolean props (having a button with three different color props).

Is our application a State Machine?

  • Yes. For example, you can turn a reducer pattern into a State Machine by adding a second reducer.
  • State Machines do a great job connecting how designers and developers work/think.
  • Designers are always thinking of State.
    • If you get a component mockup, you'll get a design with all the different State.
    • They are writing a State Machine in a visual format.

What was your favorite Component in Reach UI that was a challenge building?

  • The Listbox component was the most challenging; a Listbox presents a list of selectable options in a popover, which is toggled on or off by a button.
  • Visually and behaviorally, it is similar to @reach/menu-button except that ListboxOption components hold a value.
  • In this sense, they are more directly comparable to HTML select elements.

Listbox

  • (A bad example of this is Ant Design)https://ant.design/components/select/
    • When you open, you can't select on mouseDown. Unlike with the native select - Web/HTML/Element/select
    • People don't use native features due to ascetics preferences and the ability to add functionality.
  • Notes: you should always try to use the native elements.

React UI and XState

  • Reading the Reach UI source code is an excellent source of learning material.
  • Reach UI contains @xstate/fsm, a miniature version of XState.
  • Before XState, Ryan wrote his own Transition:
// https://github.com/reach/reach-ui/blob/a376daec462ccb53d33f4471306dff35383a03a5/packages/tooltip/src/index.tsx

/**
 * Finds the next state from the current state + action. If the chart doesn't
 * describe that transition, it will throw.
 *
 * It also manages lifecycles of the machine, (enter/leave hooks on the state
 * chart)
 *
 * @param event
 * @param payload
 */
const transition: Transition = (event, payload) => {
  let stateDef = chart.states[state];
  let nextState = stateDef && stateDef.on && stateDef.on[event];

  // Really useful for debugging
  // console.log({ event, state, nextState, contextId: context.id });
  // !nextState && console.log('no transition taken')

  if (!nextState) {
    return;
  }

  if (stateDef && stateDef.leave) {
    stateDef.leave();
  }

  if (payload) {
    context = payload;
  }

  let nextDef = chart.states[nextState];
  if (nextDef && nextDef.enter) {
    nextDef.enter();
  }

  state = nextState;
  notify();
};
  • This component also contained a StateChart, which takes the main ideas of a State Machine to handle several events.
// https://github.com/reach/reach-ui/blob/a376daec462ccb53d33f4471306dff35383a03a5/packages/tooltip/src/index.tsx

const chart: StateChart = {
  initial: IDLE,
  states: {
    [IDLE]: {
      enter: clearContextId,
      on: {
        [MOUSE_ENTER]: FOCUSED,
        [FOCUS]: VISIBLE,
      },
    },
    [FOCUSED]: {
      enter: startRestTimer,
      leave: clearRestTimer,
      on: {
        [MOUSE_MOVE]: FOCUSED,
        [MOUSE_LEAVE]: IDLE,
        [MOUSE_DOWN]: DISMISSED,
        [BLUR]: IDLE,
        [REST]: VISIBLE,
      },
    },
    
	
...
  • At the end of the day, Reach UI has a great user experience because it's designed from a component standpoint.

Research of Git History

  • Chance went back through the Reach UI git history to analyze and understand in-depth how each component has evolved over time. Then he re-engineered a new component following the Reach UI style.