Improve React Navigation with xState v5

gtodorov

Georgi Todorov

Posted on June 20, 2024

Improve React Navigation with xState v5

TL;DR

If you just want to see the code, it is here. And this is the PR with the latest changes that are discussed in the post.

Introduction

This is a short follow up post that focuses on fine tuning the navigation integration. For full context refer to the previous part. The change was inspired by a discussion in the Stately discord channel, which I recommend joining.

Improvement

As I previously stated, I use xState as the backbone of the application. The end goal is to leave all the business logic and state orchestration to the machines and use the views/screens (in this case React Native ones) for the sole purpose of displaying the correct data in a fancy way. This not only makes the application framework agnostic, but also prepares it for proper model based testing.

That's why I had concerns with how the routing logic was tightly coupled with React via the useNavigator hook. When I started using React Navigation, I thought that utilising the navigation object through props is the only way to operate with the methods that it offers and a hook seemed as the obvious choice to synchronise machines and navigation. Slowly, the application evolved to rely solely on navigationRef, which left space for improvement.

Now we can move the navigation listener from the useNavigator hook into a fromCallback actor. Invoking the actor at the root level of the machine that is in charge of the navigation provides the same functionality without the need to go through the react-specific hooks.

actors: {
  homeMachine,
  listMachine,
  navigationSubscriber: fromCallback(({ sendBack }) => {
    const unsubscribe = navigationRef.addListener("state", (_event) => {
      const screenRoute = getCurrentRouteName();

      if (screenRoute) {
        sendBack({ type: "NAVIGATE", screen: screenRoute });
      }
    });

    return unsubscribe;
  }),
},
Enter fullscreen mode Exit fullscreen mode

As an extra step we can abstract the actor and reuse it for other machines in charge of navigation. In my case I export it from machines/shared/actors.ts

The last thing that's worth mentioning from this PR is a small change in the naming convention. Each machine that is tied with a <Stack.Navigator> and supports the NAVIGATE event will be renamed to machineName.navigator.ts. Since all machines share the same folder, and only few of them are serving this special role, I think we can give them a visual distinguisher in the folder tree.

Conclusion

Since we have the base set up, the upcoming posts will focus on Registration Wizard and Notification System.

💖 💪 🙅 🚩
gtodorov
Georgi Todorov

Posted on June 20, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Improve React Navigation with xState v5
reactnative Improve React Navigation with xState v5

June 20, 2024