Release Notes: XState 4.22.0 & @xstate/react 1.5.0
Published: 2021-07-06 15:20:06

---
title: Release Notes: XState 4.22.0 & @xstate/react 1.5.0
published: true
description: Learn about the new features in XState 4.22.0 and @xstate/react 1.5.0!
tags: 
//cover_image: https://direct_url_to_image.jpg
---

## XState 4.22.0

[See release](https://github.com/statelyai/xstate/releases/tag/xstate%404.22.0)

In past releases, [`createModel(...)`](https://xstate.js.org/docs/guides/models.html) was introduced to make typing context and events easier in machines. Now, you can create a machine directly from the `.createMachine(...)` method on a created model:

```ts
const userModel = createModel({
  name: 'David'
});

const userMachine = userModel.createMachine({
  // no need to specify initial `context`!

  entry: (context, event) => {
    // context and event are fully typed from model
  }
});
```

This makes it even easier to create typed machines without having to specify type parameters. Keep in mind that the use of `createModel(...)` is _completely optional_, and meant as a helper. In the future, models will include ways to create and provide types for action objects, guards, and more.

---

In this version, you can also now spawn/invoke reducers, which are functions that return the next state given the current state and event. The source of a spawned/invoked reducer is created using `fromReducer(reducer, initialState)`:

```tsx
import { fromReducer } from 'xstate/lib/behaviors';

type CountEvent = { type: 'INC' } | { type: 'DEC' };

const countReducer = (count: number, event: CountEvent): number => {
  if (event.type === 'INC') {
    return count + 1;
  } else if (event.type === 'DEC') {
    return count - 1;
  }

  return count;
};

const countMachine = createMachine({
  invoke: {
    id: 'count',
    src: () => fromReducer(countReducer, 0)
  },
  on: {
    INC: {
      actions: forwardTo('count')
    },
    DEC: {
      actions: forwardTo('count')
    }
  }
});
```

If you've used Redux, Vuex, ngrx, or similar state management libraries that use reducers, this should feel familiar to you. It is now possible to reuse reducers directly inside of XState.

## `@xstate/react` 1.5.0

[See release](https://github.com/statelyai/xstate/releases/tag/%40xstate%2Freact%401.5.0)

Just like `useInterpret(...)` takes in a machine and returns a service actor, there is a new `useSpawn(...)` hook that takes in any _behavior_ and returns an actor for that behavior. 

{% details What is a behavior? %}
A behavior is a function that determines _what happens next_ when an actor receives an event, depending on its current state. With state machines & statecharts, the behavior is formally and visually defined. 
{% enddetails %}

You can try this out with the previously mentioned new `fromReducer(...)` creator, which creates a "reducer behavior" from a reducer:

```ts
import { fromReducer } from 'xstate/lib/behaviors';
import { useActor, useSpawn } from '@xstate/react';

type CountEvent = { type: 'INC' } | { type: 'DEC' };

const countBehavior = fromReducer(
  (count: number, event: CountEvent): number => {
    if (event.type === 'INC') {
      return count + 1;
    } else if (event.type === 'DEC') {
      return count - 1;
    }

    return count;
  },
  0 // initial state
);

const Component = () => {
  const countActorRef = useSpawn(countBehavior);
  const [count, send] = useActor(countActorRef);

  return (
    <div>
      Count: {count}
      <button onClick={() => send({ type: 'INC' })}>Increment</button>
      <button onClick={() => send({ type: 'DEC' })}>Decrement</button>
    </div>
  );
};
```

For brevity, you can also combine the hooks:

```tsx
const [count, send] = useActor(useSpawn(countBehavior));
```

On a more general note, this demonstrates that the most basic units in XState are **behaviors** and **actors**. Actors are live instances of behaviors. State machines and statecharts are specialized, powerful behaviors, and services are actors that have their behaviors described as those state machines/statecharts.