React + Redux + Storybook:写storybook故事时如何使用connected react router的useParams?

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

我有一个反应组件,它从路由中获取 id 并使用它来加载一些数据并填充 redux 状态。

我正在使用 'react-router' 中的 useParams 来执行此操作。

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

我有一个故事

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({})

preloadData装饰器只是

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

代码在站点中实际 运行 时一切正常,但是当 运行 在故事中时,路径中没有 :iduseParams 获取.

现在我将跳过这个故事,只测试 Display 组件,但我这个完美主义者需要知道如何让它工作。

我们在尝试为其中一个页面创建故事书时遇到了类似的挑战。我们在 Medium -> link 上找到了解决方案。所有学分和特别感谢作者。

解决方案是使用 react-router 中可用的 MemoryRouter

在我们的解决方案中,我们使用了故事书 Decorators,其中 return 由 MemoryRouter 和 Router 包装的故事 ->

return ( <MemoryRouter initialEntries={["/routeName/param"]} <Route component={(routerProps) => <Story {...routerProps} />} path="/routeName/:paramName"/> </MemoryRouter>)

希望这对遇到同样挑战的每个人都有帮助。

我也遇到了问题,De2ev 的评论为我指明了正确的方向。然而它并没有直接工作,我不得不做一些细微的改变。最后它使用以下代码工作:

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 />;

遇到同样的问题并完成如下

export default {
      title: 'Common/Templates/Template Rendering',
      component: CasePage
    }
    //  We create a “template” of how args map to rendering
    const Template: Story<any> = (args: any) => {
      const { path } = args
      return (
        <MemoryRouter initialEntries={path}>
          <Route
            component={(routerProps: any) => <CasePage {...routerProps} />}
            path="/dcp/:caseId"
          />
        </MemoryRouter>
      )
    }
    
    export const TemplateBoxesRendering = Template.bind({})
    TemplateBoxesRendering.args = { path: ['/dcp/FX77777'] }
    
    export const TemplateBoxes = Template.bind({})
    TemplateBoxes.args = { path: ['/dcp/FX22222'] }

我在使用 Storybook 6.3+ 和 React Router 6.00-beta 时遇到了同样的问题,必须用 <Routes></Routes> 包裹 <Route> 才能正常工作。

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

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

export const Default = () => <MyComponent />;