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
代码在站点中实际 运行 时一切正常,但是当 运行 在故事中时,路径中没有 :id
供 useParams
获取.
现在我将跳过这个故事,只测试 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 />;
我有一个反应组件,它从路由中获取 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
代码在站点中实际 运行 时一切正常,但是当 运行 在故事中时,路径中没有 :id
供 useParams
获取.
现在我将跳过这个故事,只测试 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 />;