How to Easily Set Up a React Storybook App
Tags: react, storybook, javascript, tutorial
Published: 2021-03-14 10:28:08

One of the greatest parts about React is the giant ecosystem of components created by thousands of devs all over the world.

I'm sure you've wondered at some point, how can I contribute something of my own to this? Is it simple? How can I share only my components without just pasting raw code? I suppose I could just have a project with no UI, but then how would I test my components? 😕

I'm going to go over how to create and test your UI library. Here we go! 🚀

## Enter Storybook 📕

[Storybook](https://storybook.js.org/) is an open source tool that makes creating UI libraries extremely easy. Let's get your Storybook project up and running! 🏃‍♀️

**🧶Note: I am going to be using yarn throughout this tutorial, however, any package manager works**

Let's head over to our terminal and set up a new yarn project 

```bash
# Creating a new directory to put our project into
mkdir storybook-demo

# Changing our current directory to our project directory
cd storybook-demo

# Setting up a yarn project (feel free to use the -y flag)
yarn init

# Opening our directory in our text editor (I use VSCode)
code .
```

Now let's open up our `package.json` that was created in our directory, if you're using yarn it'll look like this:

```json
{
  "name": "storybook-demo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT"
}
```

Let's head back to our terminal and add React to our project

```bash
# Add react and react-dom to devDependencies
yarn add react react-dom -D
```

Now your `package.json` should look something like this:

```json
{
  "name": "storybook-demo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  }
}
```

Sweet! Now let's create an `src` folder.

```bash
# create an src folder
mkdir src
```

Cool, we'll mess with the folder structure a little more, but this is sufficient to reliably set up Storybook in our project.

Go ahead and run this in your terminal:

```bash
npx sb init
```

**📝Note: Make sure you have react in your project before running this command, storybook uses information provided in your `package.json` to initialize itself**

As you wait for this to work its ✨magic✨, you can take a trip over to the [Storybook docs](https://storybook.js.org/docs/react/get-started/install) to read a little more about it.

One that finishes, you'll notice some differences to your project, let's start by going into our `package.json`

```json
{
  "name": "storybook-demo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "^7.13.10",
    "@storybook/addon-actions": "^6.1.21",
    "@storybook/addon-essentials": "^6.1.21",
    "@storybook/addon-links": "^6.1.21",
    "@storybook/react": "^6.1.21",
    "babel-loader": "^8.2.2",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "dependencies": {},
  "scripts": {
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook"
  }
}
```

Great! Storybook has recognized that we have react in our project (as seen with the `@storybook/react` dependency). Also take note of the two new scripts that have been added to our project, we'll look more at the first one later.

*If you've never used storybook before, feel free to run this command and explore!*

```bash
# for yarn
yarn storybook

# for npm
npm run storybook
```

If you look at your file structure, you'll also notice two new folders have been introduced: `.storybook` and `src/stories`

For the means of this tutorial, we are going to leave `.storybook` alone, as all of the default configurations suit our needs. Refer to the docs if you find the need to change things up.

But let's take a look into the `src/stories` folder

You'll see something looking like this:

```
src/stories
| /assets
| button.css
| Button.js
| Button.stories.js
| header.css
| Header.js
| Header.stories.js
| Introduction.stories.mdx
| page.css
| Page.js
| Page.stories.js
```

Take note of how this is structured, as this is entirely viable Storybook code! However, I think we can make something more robust and more easily scalable by bettering the file structure of our project

So let's delete the contents!

```bash
# change to stories directory
cd src/stories

# remove the contents
rm -rf *
```

We'll come back to that later... let's set up a UI component! We'll be making a simple button, but feel free to make whatever you would like 

```bash
# change to our src directory (assuming you're in src/stories)
cd ..

# create a components directory
mkdir components

# change to our components directory
cd components

# create a Button.js file in our components directory
touch Button.js

# open Button.js in our editor
code Button.js
```

For the sake of simplicity, we're going to keep this component pretty barebones, we can iterate more on this later.

```jsx
// src/components/Button.js
export const Button = () => {
	return <button>I am a Button!</button>;
};
```

Now we need to set up a story for our Button. Let's create a file:

```bash
# Go to stories dir (if you're still in src/components)
cd ../stories

# Create a Button.stories.js in our stories directory
touch Button.stories.js

# Open it in our editor
code Button.stories.js
```

Still with me? Now let's put in some code to test out Storybook

We can think of our story as a mini React project. We'll walk through the basics of making a story, but you can check out the docs on a more in depth explanation of what a story is [here](https://storybook.js.org/docs/react/get-started/whats-a-story)

Go ahead and put this into your `Button.stories.js` file:

```jsx
// Button.stories.js

// import React and stories from storybook
import React from "react";
import { storiesOf } from "@storybook/react";

// import our Button component
import { Button } from "../components/Button";

// create our stories
const stories = storiesOf("Button Test", module);

// add to our stories
stories.add("Button", () => {
	return <Button />;
});
```

This simple story is going to just display our Button component that we created earlier, as to maintain simplicity

Also! Since our story behaves like a React app, we need to import React. This also applies if we choose to use hooks.

Now let's see if our story works!

```bash
# for yarn
yarn storybook

# for npm
npm run storybook
```

You should see something like this pop up in your browser:

![Storybook localhost UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zomcix5nqso1o1mayoxk.png)

Great! Now everything is up and running. We can do just about anything we want with our storybook, from creating an entire UI library, to testing out how our different UI components work together.

I'll give a quick (albeit very very simple) example with the Button component that we made. After that I'll send you off on your own! ✈

```jsx
// src/components/Button.js
export const Button = ({
	bgColor = "lightblue",
	children = "Button",
	...props
}) => {
	return (
		<button style={{ backgroundColor: bgColor }} {...props}>
			{children}
		</button>
	);
};
```

This simple Button component takes in a `bgColor` prop, it's `children`, and then also passes it's rest of its `props` (for instance 'onClick')

Now let's make this do something within our story!

```jsx
// src/stories/Button.stories.js

import React from "react";
import { storiesOf } from "@storybook/react";

import { Button } from "../components/Button";

const stories = storiesOf("Button Test", module);

stories.add("Button", () => {
	const handleClick = () => {
		alert("You clicked the button!");
	};

	return (
		<Button bgColor="white" onClick={handleClick}>
			This is the Button's children
		</Button>
	);
});
```

I added in an `onClick` handler, a prop for our `bgColor`, and filled in the Button's children with some generic text. 

And with our Storybook magic, we've created this! 🎉

![Storybook app UI with new Button code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uyigppq8hi2a45qi07df.png)

I hope this tutorial was helpful to you! I personally plan on using Storybook for creating any UI based libraries I make, what about yourself? 

Until then, code on! 👩‍💻

PS: Here's the [source code](https://github.com/KyleMcKell/storybook-demo)