React Single File Components with XState
Tags: react, xstate
Published: 2020-03-29 11:23:55

---
title: React Single File Components with XState
published: true
description: React Single File Components with XState
tags: [react, xstate]
---

After reading [React Single File Components Are Here](https://dev.to/swyx/react-single-file-components-are-coming-3g74) by @swyx and trying out [RedwoodJS's Cells](https://redwoodjs.com/tutorial/cells) I noticed these SFC's look a lot of state machines!

Shawn's first example (reduced for brevity):
```javascript
export const QUERY = gql`
  query {
    posts {
      id
      title
      body
      createdAt
    }
  }
`;

export default function MyComponent() {
  const { loading, error, data: posts } = useQuery(QUERY);
  if (error) return <div>Error loading posts: {error.message}</div>;
  if (loading) return <div>Loading...</div>;
  if (!posts.length) return <div>No posts yet!</div>;

  return posts.map(post => (
    <article>
      <h2>{post.title}</h2>
      <div>{post.body}</div>
    </article>
  ));
}

```

Looks a lot like something you would do using `xstate`:
```javascript
export const fetchMachine = Machine(...);

export default function MyComponent() {
  const [state, send] = useMachine(fetchMachine);
  const { error, posts } = state.context;

  if (state.matches("error"))
    return <div>Error loading posts: {error.message}</div>;

  if (state.matches("loading")) return <div>Loading...</div>;

  if (!posts.length) return <div>No posts yet!</div>;

  return posts.map(post => (
    <article>
      <h2>{post.title}</h2>
      <div>{post.body}</div>
    </article>
  ));
}

```

## Redwood Cells

Here's what Redwood Cells look like:
```javascript
export const QUERY = gql`
  query {
    posts {
      id
      title
      body
      createdAt
    }
  }
`;

export const Loading = () => <div>Loading...</div>;

export const Empty = () => <div>No posts yet!</div>;

export const Failure = ({ error }) => <div>Error loading posts: {error.message}</div>;

export const Success = ({ posts }) => {
  return posts.map(post => (
    <article>
      <h2>{post.title}</h2>
      <div>{post.body}</div>
    </article>
  ));
};
```

Behind the scenes, Redwood executes the exported GraphQL query and renders the component that matches the state of the request automatically.

What if we could write the UI for our state machine in such a way? For every state you could export a matching component. Let's say our state machine from the previous example looks something like this:

![State Machine for Fetch Requests](https://dev-to-uploads.s3.amazonaws.com/i/5ut4ch0m1rqdlp3kq9sk.PNG)

A basic machine that fetches an arbitrary request, saves the data on success and saves the error on failure. It could have the exact same SFC implementation as a Redwood Cell!

But what about a different state machine? Let's try this one:

![State Machine for a Flower](https://dev-to-uploads.s3.amazonaws.com/i/6jlqvg8hoo2zs6lzqs3d.PNG)

It's a very basic machine for a flower that starts as a seedling, grows when you water it, wilts when you don't water it, and dies when you don't water it when it's wilting. Check it out in the sandbox below!

{% codesandbox xstate-sfc-yn8hf %}

How would the code for this machine UI look in a SFC format? I'd say kind of like this:

```javascript
export const Seedling = () => 🌱

export const Grown = () => 🌹

export const Wilting = () => 🥀

export const Dead = () => 💀
```

Cool, right? Now this example is pretty basic, but it makes the UI very readable. Another potential benefits to defining state UI this way could be that if you pass your machine's context to the SFC you can be certain of some piece of context being available inside a state component, eliminating the need for `null` checks. Kind of like with [`TypeStates`](https://xstate.js.org/docs/guides/typescript.html#typestates)

E.g. in the fetch example:

```javascript
export const Success = ({ context }) => {
  // Here I am certain context.data is available. No need for
  // if (context.data) return </Stuff >
  // or even
  // state.matches('success') return <Stuff />
  // The latter is abstracted away in our tooling
}
```


## Ok, but why?
Is this useful? I'm not sure! It has the benefits of single file components, it _could_ make your state machine-driven UI more readable, it _might_ prevent _even more_ bugs than using state machines in general, but doing this would probably also have some downsides.

What if I want some piece of UI to be shared between multiple states? The plant example has 3 states that allow you to water (seedling, grown, wilting) and 1 state that doesn't (dead). Now what? Do I duplicate the watering UI 3 times? Maybe that piece of UI should live outside of my state component? Or perhaps I think about re-designing my machine. I could change my machine to look like this:

![State Machine for Plant](https://dev-to-uploads.s3.amazonaws.com/i/snasowoso6ylpvdx5y4y.PNG)

It now has 2 main states, alive and dead. You can only water it when it's alive. This would change my file to export 2 components: `Alive` and `Dead`. Where `Alive` needs some kind of way to display the sub machine. Perhaps a second file with `Seedling`, `Grown` and `Wilting`, I don't know, I didn't think this far yet!

To conclude; these are all just thoughts, and since you've made it this far, I'd love to hear yours as well! Do you think defining your UI this way could be useful, or it's just limiting?