How and Why to Add a Storybook.js Design System to Your Existing React Application
By: Matthew Weeks
Tags: JavaScript, React, Developer Tools, Nodejs, Programming

Start Adding Non-Trivial Components As You Work

Whenever you are updating the design of a component, it is good practice to add a story file to Storybook for it. In 80% of cases, it takes just a few minutes to add a *.stories.js .

“A story captures the rendered state of a UI component. Developers write multiple stories per component that describe all the ‘interesting’ states a component can support.” — Storybook docs

You will typically have one story for each state that your component has:

This is as basic as a story can get and doesn’t take advantage of Storybook’s additional tooling, which I will describe a bit later on.

If a story has any complications, like dependency on a context you haven’t had to mock yet or some other mysterious issues (they do occasionally crop up), leave it to your best judgment to make it work rather than completing your work. If it’s just some small content change on some page, then it’s probably not worth the distraction.

You have two options.

1. Refactor your components and export a stateless version

This is often the best approach when building new components. These sorts of outside dependencies are often done unintentionally. They were not being built with re-use or modularity in mind. The time spent refactoring could make it easier to demonstrate hard-to-access states in components and will effectively serve as a set of visual unit tests for your components.

Once your component exports a functional stateless UI component, you can add it to Storybook:

In this example, you will notice that we are using Storybook’s args. These can get complicated, but they are essentially a more portable means of setting the props for a particular story.

In this example, the Header component has been made into a stateless component and the two states ( header and authenticatedHeader ) each have their own story, with the userProfile object being passed in as a prop.

2. Work with what you have and make a provider for it

If the component you’re working with is a higher-order organism component like a page with nested connected components, you may need to wrap it in a provider.

This could either be a mock or even an actual instance of the dependency. This means you will be displaying the components similarly to how they are used in the application, and it will likely be the easiest way to get it working.

For example, let’s say you are working on a React/Redux application and want to add your page component that contains nested connected components and perhaps some React Router links. This would require you to include a Redux context and React Router context:

You’ll notice that I’ve done this with decorators. These are simple functions that can modify each story with extra markup and more. In this case, it makes for a pretty clean way to add multiple providers.

To display different states, you can dispatch simple events yourself:

You’ll notice that I had to dispatch a logout action here. This is because, in this case, my stories each share the same global instance of the store.

However, if we were to take this a step further and mock our store, then we could create a reset method. In this case, I didn’t have the time or need for a mock — and I want to keep things simple — so I simply used my existing store.

Remember, we’re trying to be pragmatic here. We just want a single pristine example of how our component is used.