Storybook w/ react-router - 你不应该在 <Router> 之外使用 <Link>
Posted
技术标签:
【中文标题】Storybook w/ react-router - 你不应该在 <Router> 之外使用 <Link>【英文标题】:Storybook w/ react-router - You should not use <Link> outside <Router> 【发布时间】:2020-03-13 12:48:24 【问题描述】:发布一个问题的解决方案,尽管 Sensei 谷歌搜索技能我很难找到
虽然我的带有 react-router 的应用程序正常运行,但 Storybook 抛出了错误“Invariant failed: You should not use outside”。
Error: Invariant failed: You should not use <Link> outside a <Router>
at invariant (tiny-invariant.esm.js:11)
at react-router-dom.js:181
at updateContextConsumer (react-dom.development.js:19747)
at beginWork$1 (react-dom.development.js:20079)
at htmlUnknownElement.callCallback (react-dom.development.js:358)
at Object.invokeGuardedCallbackDev (react-dom.development.js:410)
at invokeGuardedCallback (react-dom.development.js:463)
at beginWork$$1 (react-dom.development.js:25730)
at performUnitOfWork (react-dom.development.js:24631)
at workLoopSync (react-dom.development.js:24613)
奇怪,因为应用程序正常工作(因此没有在外面使用)。
【问题讨论】:
【参考方案1】:这对我有用:
-
在您的
.storybook
文件夹中创建一个preview.js
文件。
在您的 preview.js
文件中添加以下全局装饰器。
import React from "react";
import addDecorator from "@storybook/react";
import MemoryRouter from "react-router";
addDecorator(story => <MemoryRouter initialEntries=['/']>story()</MemoryRouter>);
备注
使用的故事书版本:"@storybook/react": "^5.3.13"
基于此解决方案here
更多关于全局装饰器here
【讨论】:
这是方式,应该是公认的解决方案 好,我只是将 importreact-router
切换到 react-router-dom
【参考方案2】:
这对我有用。在 decorators 属性中添加 Memory Router。
import React from 'react';
import MemoryRouter from 'react-router-dom';
import //your component// from //component location//
export default
title : //How you want your component to show in storybook eg: 'Components/Button'
component : //Specify the name of component that you imported eg: 'Button'
decorators : [(Story) => (<MemoryRouter><Story/></MemoryRouter>)] //Wrapping the story inside the router
;
【讨论】:
【参考方案3】:对于 Storybook 的 6.1 版,storybook-router 采用新的代码表示法。以下是单个组件的示例:
import React from 'react';
import StoryRouter from 'storybook-react-router';
import //your component// from //component location//
export default
title: '//your component//',
component: //your component//,
decorators: [StoryRouter()],
;
export const Name = () => <//your component// />;
【讨论】:
【参考方案4】:进一步了解 Web-ski 的答案。将 StoryRouter 添加到您的 .storybook/preview.js
import StoryRouter from 'storybook-react-router';
addDecorator(StoryRouter());
它现在在全球范围内,在每个故事中都可用。
【讨论】:
【参考方案5】:如果您想为单个组件而不是全局执行此操作,则在故事文件中,将组件包装在内存路由器中。
例如,我有一个包含 Link 元素的标题组件,因此在我的 header.stories.tsx 文件中,我将更改以下内容:
const Template: ComponentStory<typeof Header> = (args) => (
<Header ...args />
);
到
const Template: ComponentStory<typeof Header> = (args) => (
<MemoryRouter>
<Header ...args />
</MemoryRouter>
);
【讨论】:
【参考方案6】:问题在于 Storybook 呈现各个故事。在这种情况下,使用<Link>
的组件实际上是在<Router>
之外呈现的。
解决方案是使用 addDecorator 用 <Router>
包装各个故事;
//config.js
//...
addDecorator(story => <Router>story()</Router>);
【讨论】:
以上是关于Storybook w/ react-router - 你不应该在 <Router> 之外使用 <Link>的主要内容,如果未能解决你的问题,请参考以下文章
MUI v5 + Storybook:主题和字体系列在 Storybook 中不起作用
如何使用 Storybook 6 在 Vuetify 中自定义主题?