Should You Use React Storybook?

Our team recently started using React Storybook for a large React app that we have been building. In this post, I’ll share what we learned and hopefully encourage you to consider incorporating Storybook into your next React project.

What is React Storybook?

Storybook allows you to run and view your React components in an a-la-carte, isolated manner. Imagine developing a component, and then just firing it up by itself.

Assuming your component receives props as input, Storybook allows you to pass in some props values when instantiating it. It also has several handy add-ons that allow you to parameterize your props and try different values when viewing your component—more on that later.

This is how the Storybook docs describe what it does:

Storybook is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.

Storybook runs its own web server, separate from your React app, and provides a catalog view for the components that you choose to use it with. The Storybook docs have a nice selection of sample Storybook catalogs. Below is a screenshot of the Carbon Components example.

Notice how their components are grouped into different categories such as “Link,” “Modal,” “RadioButton,” etc.

Why Is It Useful?

As developers, our goal is usually to build software incrementally, with the goal of new features being written in a modular manner. To ensure that our code operates correctly, we usually capture its behavior in a set of unit tests. These tests exercise our code in an isolated way. However, when we later go to manually test our components, it’s typically done within the context of the full website.

Storybook allows you to see and interact with your components in an isolated way, similar to how unit tests scope the testing of your component code. This does a couple of interesting things:

  1. It allows you to work in a more incremental and isolated manner. Storybook lets you build and manually test your components before you write a container (assuming you are using Redux) to provide props to it. You also don’t need to worry about where your component will live.
  2. It surfaces questions around ownership of layout and styles. Should your component define its own width, or should that be left up to its parent? These types of questions are immediately surfaced when you view your component in Storybook, because it allows you to see how your component behaves outside of the context of your application.
  3. It makes situations that are difficult to manually test easy. How many times have you updated your computer’s clock/time settings, just to spot check some piece of functionality that depends on the current date or time? With Storybook, you can just write a story and (assuming your component takes in a date as one of its props) pass in any date to allow for testing different scenarios. You can even wire up a date knob and allow your Storybook users to change the date easily.

Our Experience

Our team started developing without Storybook. After introducing it, we went back and added stories for some of our more widely used components. Surprisingly, when some of these components were run in isolation, they were not being styled correctly. This exposed issues in our code where certain components were relying on their parents for styling specific parts of them–an issue we certainly wanted to fix, especially because these components were planned to be re-used on different pages later on.

Storybook also makes testing and updating components more accessible to non-developers. You could expose your Storybook component library to your customer, client, or QA team and allow them to manually test how different situations are reflected in your component’s UI.

Storybook Tips

All of this probably sounds great. However, you might be wondering how much technical effort is required to use and maintain Storybook, or if you need to change your development approach to better write components that can easily be used with Storybook.

Setup and execution

Setting up and running Storybook will depend on your application’s build configuration. We use webpack to build our TypeScript React app, so we had to create a Storybook-specific webpack config file. Storybook docs provide a nice description for different build configurations.

Add-ons

The Storybook creators and community have developed several Addons that provide a nice set of additional functionality. The one we’ve used most is the Knobs Addon. Knobs allow you to expose your component props in the form of UI controls, like a text box for string props, a slider for numeric props, a calendar picker for date props, etc.

Code organization

There are some technical tips that are useful when writing a story for certain components.

If you are using React Router and your component happens to link to a different page, you will need to do something to allow your component to be rendered without being embedded in a Router component. We relied on this storybook-router Storybook decorator., which can be used via:


const StoryRouter: any = require('storybook-router');

storiesOf("Components", module)
  .addDecorator(StoryRouter.default())
  .add("My Story", () => {
    return (<MyComponent />);
  });

This allows the MyComponent component to be rendered by Storybook, despite it expecting to be embedded in a Router component.

Ideally, your Storybook stories should just test your view components. In practice, though, it is sometimes difficult to isolate your view components from their containers. For example, perhaps you want to write a story for a large component that is comprised of many smaller components, some of which are wrapped by containers. You can still use Storybook in these situations. This post describes how you might go about supporting components that require Redux with Storybook.

If you are using Apollo or other GraphQL libraries, there is a GraphQL storybook addon.

Summary

After using Storybook, we learned that for ease of writing stories and just better design in general, it is preferable to push your container components as far as possible from your display components. We had previously been quick to wrap components with containers, even if those containers were then used by other display components (it’s very easy to do this with libraries like Apollo). This makes it much more difficult to render your components in isolation and use them with Storybook.

If you are using Storybook, I’d love to hear about your experience.