Managing state in React can become cumbersome as the application logic grows increasingly complex. Third-party libraries such as Redux, Flux, and MobX help, but even these tools come with their own overhead.

A state machine, also called a finite state machine or finite state automata, is a mathematical model of computation. It is an abstract machine with a finite number of states at any given time.

In this guide, we’ll review the similarities, differences, pros, and cons of two state machines — XState and Robot — and walk through how to use them to simplify state management in React applications.

Why use a state machine?

State is an important part of most frontend applications, especially in React. Think of state as a representation of the part of an application that changes.

Consider a component that fetches data from an API.

const Todo = () => {
  const [data, setData] = useState([]);

  const handleClick = () => {
    fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json())
    .then(todo => setData(data.push(todo))
    .catch(error => console.error(error) )
  }
  return(
    <div>
      <button onClick={handleClick}> Fetch Data </button>
      {data && data.map(todo => (<p key={todo.id}> {todo.title} <span> {todo.completed} </span></p>) )}
    </div>
  ); 
}

In this example, data is our state since it’s the part of the application that changes whenever an event occurs — in this case, the click of a button. The problem with this setup is that it can become complicated.

What happens while the user waits for the record to be fetched or if an error occurs while fetching? We need to add more states to handle these problems.

const Todo = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState([]);
  const [isError, setIsError] = useState(false);

  const handleClick = () => {
    setLoading(true);
    fetch('https://jsonplaceholder.typicode.com/todos/1')
      .then(response => response.json())
      .then(todo => {
        setLoading(false);
        setData(data.push(todo));
      })
      .catch(error => {
        setLoading(false);
        setIsError(true);
      })
  }
  return(
    <div>
      {loading && <p> Loading Data... </p>}
      <button onClick={handleClick}> Fetch Data </button>
      {data && data.map(todo => (<p key={todo.id}> {todo.title} <span> {todo.completed} </span></p>) )}
      {error && <p> An error occured. Try again.</p>}
    </div>
  ); 
} 

If your application is complex, things can quickly spiral out of control as new features are added, making your code difficult to understand, test, and enhance.

State machines approach this unique problem differently. With state machines, you can define all the states that our application can be in, the transitions between the states, and the side effects that can occur. This helps you avoid a situation where the application is in an impossible state.

State Diagram

Our application can be in the following states:

  1. ready — the initial state when the application starts up
  2. loading — when an event occurs i.e a button is clicked
  3. success — when loading resolves
  4. error — when loading is rejected

The app transitions from one state to another when an action is triggered — i.e., when a user clicks a button. You have better control of your application when you can anticipate all the possible states it can be in.

What do XState and Robot do?

According to its official documentation, XState is a library for creating, interpreting, and executing finite state machines and statecharts, as well as managing invocations of those machines as actors. It was created by David Khourshid to address the problems of state in user interfaces.

Robot is a lightweight, functional, and immutable library created by Mathew Philips for building finite state machines. It was inspired by XState, Statecharts, and the P programming language.

#react #javascript #developer

Comparing State Machines: XState vs. Robot
10.85 GEEK