Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React + Redux + Storybook: How to use connected react router's useParams when writing storybook stories?

I have a react component that grabs an id from the route and uses that to load some data and populate the redux state.

I am using useParams from 'react-router' to do this.

import { useParams } from 'react-router'

import { usePreload } from './hooks'
import Display from './Display'

const Overview = () => {
  const { id } = useParams()
  const { data } = usePreload(id) // uses useEffect to preload the data with the given id

  return <Display data={data} />
}

export default Overview

I've got a story

import Overview from './Overview'

import preloadData from './decorators/preloadData'

export default {
  title: 'Redux/scenes/Overview',
  decorators: [preloadData()],
  component: Overview,
  argTypes: {}
}

const Template = args => <Overview {...args} />

export const Default = Template.bind({})

The preloadData decorator is simply

import { usePreload } from '../hooks'
import { data } from './fixtures'

const Loaded = ({ children }) => {
  useSubmissionsPreload(data.id) // loads the site data into the state

  return <>{children}</>
}

const preloadData = () => Story => (
  <Loaded>
    <Story />
  </Loaded>
)

export default preloadData

The code all works fine when actually running in the site but when running within a story there is no :id in the path for useParams to pick up.

For now I am just going to skip this story and just test the Display component, but the completist in me demands to know how to get this to work.

like image 971
Dave Sag Avatar asked Nov 20 '20 05:11

Dave Sag


People also ask

How do you use a Router in storybook?

To add the router to all the stories of a component, simply add it to the decorators array. Note that the parameters. reactRouter property is optional, by default the router will render the component at / .

Can I use Redux with react Router?

You can use the connected-react-router library (formerly known as react-router-redux ). Their Github Repo details the steps for the integration. Once the setup is complete, you can now access the router state directly within Redux as well as dispatch actions to modify the router state within Redux actions.

Does react Router allows for nested routes?

With React Router, you have two options for creating nested routes. The first is using the /* with nested <Routes> pattern and the second is using the <Outlet /> pattern.


1 Answers

I also had the problem and the comment from De2ev pointed me in the right direction. It did however not work directly and I had to make slight changes. In the end it worked with the following code:

import React from "react";
import { Meta } from "@storybook/react";
import MyComponent from "./MyComponent";
import { MemoryRouter, Route} from "react-router-dom";

export default {
    title: "My Title",
    component: MyComponent,
    decorators: [(Story) => (
        <MemoryRouter initialEntries={["/path/58270ae9-c0ce-42e9-b0f6-f1e6fd924cf7"]}>
            <Route path="/path/:myId">
                <Story />
            </Route>
        </MemoryRouter>)],
} as Meta;

export const Default = () => <MyComponent />;
like image 147
astroknaut Avatar answered Sep 19 '22 11:09

astroknaut