www.thisdot.co Open in urlscan Pro
2600:9000:236e:4600:5:84f5:bec0:93a1  Public Scan

Submitted URL: https://thisdot.orhygiea.com/api/mailings/click/PMRGSZBCHI2TOOBUGUZSYITVOJWCEORCNB2HI4DTHIXS653XO4XHI2DJONSG65BOMNXS6YTMN5TS6...
Effective URL: https://www.thisdot.co/blog/xstate-with-react-for-beginners/
Submission: On February 15 via api from US — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

Skip to content
 * services
 * trainings
 * portfolio
 * about
 * blog
 * resources
    * all resources
    * books
    * events & podcasts
    * javaScript marathon
    * analyze

 * Contact Us

ReactJS


XSTATE WITH REACT FOR BEGINNERS

Mark Shenouda

Jan 10

5 min read

XStatejavascript


đź”—INTRODUCTION

When I started to learn XState for the first time, I found the docs somewhat
difficult to interpret. Perhaps this was because the docs show a number of
concepts at the same time that I was not familiar with as a developer coming
from a Redux or React Context background. So I decided to write this article to
help others learn XState step-by-step!


đź”—WHAT IS XSTATE?

XState is a state management library for JavaScript. The idea behind it is a
little bit different than Redux or React Context as it is not necessary to use a
global store or wrap the whole application in a provider. It is just a simple
way to manage the state of your application, and separate the logic from the
view so it helps you to write clean and readable code.


đź”—GETTING STARTED

In this tutorial, we will use XState with 3 React examples that will increase in
difficulty.


đź”—INTRODUCTORY LEVEL (COUNTER EXAMPLE)

In this example, we will create a simple counter application with React, and use
XState to increment and decrement the counter state.

After you create a new React project using create-react-app, clean the starter
template, and build this simple UI in the App.js file.



Now install XState, and add it using this command:

npm install xstate

Also, we will need @xstate/react to connect XState with React.

npm install @xstate/react

Now, create a new file, name it counterMachine, and add the following code:

import { createMachine, assign } from 'xstate';

export const counterMachine = createMachine({
  context: { 
    // Here, we will define the initial state of the machine
   },
  on: {
    // Here we will define the events that will trigger the transitions.
  },
});


As you can see, we are using the createMachine function from XState to create a
new machine, and we are using the context property to define the initial state
of the machine. Also, we are using the on property to define the events that
will trigger the transitions.

Now, let's create the context (the initial state to our state machine).

context: {
  count: 0,
}

Let's add our two events to our state machine.

First event is INCREMENT, and it will increment the counter by one.

on: {
  INCREMENT: {
    actions: assign({
      count: (context) => context.count + 1,
    }),
  },
}

Second event is DECREMENT, and it will decrement the counter by one.


đź”—THEN OUR STATE MACHINE IS READY. NOW LET'S USE IT IN OUR REACT COMPONENT.

Import the useMachine hook from XState React.

import { useMachine } from '@xstate/react';

And import our state machine itself.

import counterMachine from './counterMachine';

Then, add this line inside our component:

const [state, send] = useMachine(counterMachine);

So, the useMachine hook will return an array with the current state, and the
send function. And we can use the send function to trigger the events.

You can use the state in the JSX like this:

  <h1>{state.context.count}</h1>

And now, we can trigger the events:

  <button onClick={() => send('INCREMENT')}>increment</button>
  <button onClick={() => send('DECREMENT')}>decrement</button>

And here is the result:

As you see, it's very simple. Now, let's take a step forward and create an
intermediate level example.


đź”—INTERMEDIATE LEVEL (TODO EXAMPLE)

Now we understand how to create a state machine and how to use it in React.
Let's create a Todo application to learn how to pass a payload to the state
machine.

We will use a template similar to the previous one.



Let's start with our state machine.

First, the context of the machine will look like this:

context: {
  todos: [],
}

and the events:

on: {
  ADD_TODO: {
    actions: assign({
      todos: (context, event) => [
        ...context.todos,
        event.todo
      ],
    }),
  },
}

And this is how we will pass the payload with the send function to the state
machine from the React component.

send('ADD_TODO', { todo: 'Learn XState' });

Try it and program the delete the todo function yourself!


đź”—ADVANCED LEVEL (TRAFFIC LIGHT EXAMPLE)

We learned how to create a simple state machine in the first example, and
learned how to pass a payload in the second example. Now, let's create a traffic
light example, and learn about the states in XState state machine.

The state of the state machine is exactly like the traffic light. When the
traffic light is red, the next state should be yellow, then green, then back to
red again.

So we will create a simple UI like this with three buttons:



Clone the repo from GitHub

And then our state machine will be like this:

export const trafficLightMachine = createMachine({
  initial: 'red',
  states: {
    red: {
      on: {
        NEXT: {
          target: 'yellow',
        },
      },
    },
    yellow: {
      on: {
        NEXT: {
          target: 'green',
        },
      },
    },
    green: {
      on: {
        NEXT: {
          target: 'red',
        },
      },
    },
  },
});

So, as you can see, we have two new properties in the state machine. initial and
states. And the initial property is the initial state of the machine. And the
states property is an object that contains all the states of the machine.

And we are using only one event which is NEXT and it will trigger the transition
to the next state.

So let's move on to the React component, and add the useMachine hook.

To know what the current state of our state machine is, we will use state.value.

<button
  className="red"
  disabled={state.value !== 'red'}
  onClick={() => send('NEXT')}
>
  Red
</button>

So as you see, for each color in the traffic light, we will have a button. And
we will disable the button if the current state is not the same as the color.
And we will add the onClick event to the button.

You can test it here:

--------------------------------------------------------------------------------

This Dot Labs is a development consultancy focused on providing staff
augmentation, architectural guidance, and consulting to companies.

We help implement and teach modern web best practices with technologies such as
React, Angular, Vue, Web Components, GraphQL, Node, and more.

Hire us

--------------------------------------------------------------------------------


MARK SHENOUDA

@MarkSShenouda@markshenouda


YOU MIGHT ALSO LIKE

ReactJS


TAMING FORMS WITH REACT-HOOK-FORM

ReactJS


REACT.JS 17: NO NEW FEATURES AND NEW JSX TRANSFORM

ReactJS


ADDING REACT TO YOUR ASP.NET MVC WEB APP

ReactJS


SUPERCHARGING NEXT.JS DEVELOPMENT WITH TAILWIND CSS


LET'S WORK TOGETHER

Do you want to have the job done? We are ready to provide our expertise!

Contact us


WE'RE HIRING

Developer AdvocateSoftware EngineerShow all jobs

This Dot Labs proudly partners with enterprises interested in transforming their
digital assets, upskilling their teams, and finding novel avenues for advanced
integration.

Sign up for our newsletters
 * services
 * trainings
 * portfolio
 * certifications
 * apprentice program
 * press releases

 * about
 * blog
 * team
 * jobs
 * contact

 * 
 * 
 * 
 * 
 * 

 * Code of Conduct
 * Privacy Policy
 * Cookie Policy
 * Terms of Use
 * +1-669-293-7368

© 2022 This Dot, Inc.
Live chat


CHAT WITH THIS DOT

Hi! How can we help you?

Close Chat Prompt

We use cookies to improve user experience and analyze website traffic. By
clicking “Accept“, you agree to our website's cookie use as described in our
Cookie Policy. You can change your cookie settings at any time by clicking
“Preferences.”
Preferences
Accept