Storybook addon that aids in running redux backed components in your stories.
Clone or download
Latest commit 5d8b556 Jan 18, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs remove dark lines around image May 25, 2018
src #8 Jan 17, 2019
.babelrc adding babel May 20, 2018
.eslintrc added edit mode to state panel May 21, 2018
.gitignore added state change component and cleaned up the redux history panel a… May 21, 2018
.npmignore Injecting addons instead of self registering with and import to avoid… May 21, 2018
README.md adding Provider Jan 17, 2019
package-lock.json #8 Jan 17, 2019
package.json #8 Jan 17, 2019

README.md

Storybook Redux Addon

Storybook Redux Addon aids in using redux backed components in your stories in Storybook.

Ideally stories are only needed for non-redux connected components, not containers. However, when writing stories for components of a redux application, it is common for the components to have conatiners as children which causes problems. This is where the Redux Addon helps out by providing a decorator and helpful panels to support container components.


Redux Addon History Panel

Demo project using the Redux Addon.

This addon is compatible with Storybook for React

Features

  • Add two panels to Storybook: Redux State and Redux History
  • Wraps stories with a React Redux Provider component
  • View and Edit the current state of the store
  • Provides Canned Action buttons which can dispatch predefined actions
  • Logs actions and maintains the time, action, previous state, next state and state diff
  • Supports time travel to previous states
  • Filter actions entries by action and state diff

Install

npm install --save-dev addon-redux

Usage

In order for the React Redux addon to function correctly:

  • it must be registered as a Storybook addon
  • its store enhancer must be used in the provided store
  • the withRedux decorator must be used in the story

Register

Similar to other Storybook addons, the Redux Addon needs to be registered with storybook before use. However, the Redux Addon also requires the addons module as shown below.

// .storybook/addons.js
import addons from '@storybook/addons'
import registerRedux from 'addon-redux/register'
registerRedux(addons)

Enhancer

To give the Redux Addon the ability to listen to and alter the store, its enhancer must be used when creating the store as shown below.

// Simplest use of the Redux Addon Enhancer
import { createStore, compose } from 'redux'
import reducer from './your/reducer'
import withReduxEnhancer from 'addon-redux/enhancer'

const store = createStore(reducer, withReduxEnhancer)

export default store

Usually the store of an application will already be using enhancers. A more realistic store setup for the Redux Addon is shown below. It includes the commonly used middleware enhancer along with some middlewares for demonstration. This example shows how the Redux enhancer can be used with other enhancers, although the store creation code can look very different between different applications.

// Realistic use of the Redux Addon Enhancer
import { createStore, compose } from 'redux'
import reducer from './your/reducer'
import createMiddlewareEnhancer from './middlewareEnhancer'
import withReduxEnhancer from 'addon-redux/enhancer'
import { applyMiddleware } from 'redux'
import invariant from 'redux-immutable-state-invariant'
import logger from 'redux-logger'

createMiddlewareEnhancer () => {
  const middleware = []
  if (process.env.NODE_ENV !== 'production') {
    // include other middlewares as needed, like the invariant and logger middlewares
    middleware.push(invariant())
    middleware.push(logger())
  }
  return applyMiddleware(...middleware)
}

const createEnhancer = () => {
  const enhancers = []
  enhancers.push(createMiddlewareEnhancer())
  if (process.env.NODE_ENV !== 'production') {
    enhancers.push(withReduxEnhancer)
  }
  return compose(...enhancers)
}

const store = createStore(reducer, createEnhancer())

export default store

Decorator (withRedux)

The Redux Addon provides a decorator that wraps stories with a react redux provider component. The provided withRedux method is a factory that requires storybook's addons module. The result then needs to be invoked with the redux addon settings for the story. There are currently three supported settings: store, state, and actions.

import React from 'react'
import { Provider } from 'react-redux'
import { storiesOf } from '@storybook/react'
import addons from '@storybook/addons'
import withRedux from 'addon-redux/withRedux'
import store from './your/store'
import Container from './your/container'

const withReduxSettings = {
  Provider,
  store,
  state: {optional: 'state to merge on start'},
  actions: [{name: 'Demo Action', action: {type: 'test'}}]
}

const withReduxDecorator = withRedux(addons)(withReduxSettings)

const stories = storiesOf('Demo', module)
stories.addDecorator(withReduxDecorator)
stories.add('default', () => <Container />

Store Setting

The store setting is required and should be set with the store of your application. To function properly, the store must be built including the enhancer provided with the Redux Addon.

State Setting

The state setting is optional. Use it if the default state returned from the store's reducers is not ideal or can be improved for the story. The object set to the store setting will be merged on top of the default store's state when the story loads.

Canned Actions Setting

The actions setting is optional. Use it to set canned (predefined) actions that are useful to test the story's component. The setting takes an array of canned action objects which contain a name and action key. A button will be appended to the Redux State Panel for each canned action object in the array. The name key is used as the label of a button. The action key holds the action object that will be dispatched when the canned action button is clicked.

// Canned Action Object
{
  name: 'Test Action',
  action: {
    type: 'test_action_type',
    date: 'action data'
  }
}

Redux Addon State Panel

Custom Decorator

Having to import the store, Provider, addons module, and the withRedux decorator in every story file is not ideal for larger applications. Instead, it is recomended to create a custom decorator in the storybook configuration folder that includes the withRedux setup.

// .storybook/decorators.js
import React from 'react'
import { Provider } from 'react-redux'
import addons from '@storybook/addons'
import withReduxCore from 'addon-redux/withRedux'
import { store } from './your/store'

export const withRedux = (state, actions) => withReduxCore(addons)({
  Provider, store, state, actions
})
//custom decorator use in story
import { withRedux } from '../../.storybook/decorators'
...
stories.addDecorator(withRedux(initialState, cannedActions))