React Navigation 5 and Storybook

12 March 2021

StoryBook navigation object not found with React Native
Photo by jeremybishop

Designing at scale is not an easy task —especially on mobile. User flows rapidly become complex and it takes a ridiculous amount of time to test every single scenario.

As a React Native developer working freelance, I code on different stacks. Today I will cover the problem I faced when I wanted to connect these tools together:

Since 2017, I follow the "Component Driven Development" way of working. Like Lego bricks, all my components are loosely-coupled and independent. I assemble them to test behavior with Storybook. But if you want to have access to the navigation you will encounter this error: {navigation} object is not defined.

The Problem

If you’ve tried creating a story component that uses the useNavigation hook, you’ve likely seen this error message:

Couldn’t find a navigation object. Is your component inside a screen in a navigator?

This happens because the useNavigation hook needs to retrieve the navigation prop from a parent Screen component, and you’re most likely rendering the component in isolation. This leads to an error since the hook is not able to retrieve the navigation prop.

Couldn't find a navigation object.

Don’t panic. I found the solution.

Solution: Wrapping your Story component with a decorator

You could create a MockedNavigator component as described on this tread on GitHub.

// storybook/StoryNavigator.tsx

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

/**
* Helper component tor create a Dummy Stack to access {navigation} object on *.story.tsx files
*
* @usage add this decorator
* ```
* .addDecorator(reactNavigationDecorator)
* ```
*/

const StoryBookStack = createStackNavigator();

export const reactNavigationDecorator = (story) => {
const Screen = () => story();
return (
<NavigationContainer independent={true}>
<StoryBookStack.Navigator>
<StoryBookStack.Screen
name="MyStorybookScreen"
component={Screen}
options={{header: () => null}}
/>
</StoryBookStack.Navigator>
</NavigationContainer>
);
};

and then you can addDecorator

import {reactNavigationDecorator} from '~/storybook';

storiesOf('ScrollTabBar', module)
.addDecorator((fn) => <StoryScreen>{fn()}</StoryScreen>)
.addDecorator(reactNavigationDecorator)
.add('Style Presets', () => (
<Story>
<UseCase text="ScrollViewWithTabBar" usage="children">
<ScrollViewWithTabBar>
<DummyContent />
</ScrollViewWithTabBar>

The benefit of this approach is that it provides an actual navigation prop to the component.

Gravatar for dleuliette@gmail.com

Hi, I’m David, a french freelance developer working remotely. I’m the author of this blog, nice to meet you!

Subscribe?

Be the first to receive insightful articles and actionable resources that help you to elevate your skills across every touch point.