Improve React Navigation with xState v5
Georgi Todorov
Posted on June 20, 2024
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;
}),
},
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
.
Posted on June 20, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.