Reputation: 316
We are building a Storybook UI library from our existing code base. The code wasn't written with component driven development in mind. There are many instances where a component renders descendants that are connected to the Redux store.
E.g., Parent (connected) -> Child (unconnected) -> Grandchild (connected)
Now if I'm building a story for Parent, I understand how to pass hard-coded data as a prop to an immediate child component in order to avoid Redux all together. However, I can't figure out how to do this when the connected component is more deeply nested.
Ideally I don't want to have to use Redux at all for stories, but even if I do initialize a Redux store and wrap the parent component in a Provider as described here, would this even work to connect the grandchild component?
Any ideas would be helpful.
Upvotes: 19
Views: 23194
Reputation: 9441
If you want to solve the problem within your story file (and just fetch your store), use decorator like this:
import React from "react";
import { Provider } from 'react-redux'
import Parent from "./Parent";
import { store } from "../../../redux/store";
export default = {
title: "pages/Parent",
component: Parent,
decorators : [
(Story) => (<Provider store={store}><Story/></Provider>)
]
};
Sidenote, if this gives you the error useNavigate() may be used only in the context of a <Router> component.
, then you may need <MemoryRouter><Provider store={store}><Story/></Provider></MemoryRouter>
(import {MemoryRouter} from 'react-router-dom'
)
Upvotes: 4
Reputation: 53934
When using storybook
you can add a Decorator for all stories (see link for most updated API).
It is common to wrap your stories with the state manager store provider in order to not break the story avoiding "adding a store
for each story".
// @ config.js
import { configure, addDecorator } from '@storybook/react';
import React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from 'reducers/root.reducer';
const store = createStore(rootReducer);
addDecorator(S => (
<Provider store={store}>
<S />
</Provider>
));
configure(require.context('../src', true, /\.stories\.js$/), module);
Note that you can avoid connect
ing all your components with redux-hooks which in addition removes all the boilerplate code of redux.
React Redux now offers a set of hook APIs as an alternative to the existing connect() Higher Order Component. These APIs allow you to subscribe to the Redux store and dispatch actions, without having to wrap your components in connect().
Upvotes: 24