reactjs 带React路由器的故事书-您不应在外部使用< Link>< Router>

deikduxw  于 2022-12-12  发布在  React
关注(0)|答案(7)|浏览(204)

张贴的解决方案,以一个问题,我有一个很难找到,虽然唤醒谷歌技能
虽然我的应用程序与react-router工作没有任何问题Storybook抛出错误“不变失败:你不应该在外面使用“。

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)

奇怪的是,因为应用程序的工作(因此没有使用以外)。

evrscar2

evrscar21#

以下是对我有效的方法:
1.在.storybook文件夹中创建一个preview.js文件。
1.在您的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的更多信息
    编辑:故事书V7更新(2022年12月)

1.将preview.js重命名为preview.tsx(我想它在jsx中也会起作用,但我的项目是用TypeScript制作的)

  1. addDecorator函数不再适用于v7,因此您需要像这样添加它。
import React from "react";
import { MemoryRouter } from "react-router";
    
export const decorators = [
  (Story) => (
    <MemoryRouter initialEntries={['/']}>
      <Story />
    </MemoryRouter>
  ),
];
xhv8bpkk

xhv8bpkk2#

这对我来说是有效的。在装饰器属性中添加内存路由器。

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
};
ohtdti5x

ohtdti5x3#

对于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// />;
l3zydbqr

l3zydbqr4#

Web-ski的答案是:将StoryRouter添加到您的.storybook/preview.js

import StoryRouter from 'storybook-react-router';

addDecorator(StoryRouter());

它现在在全球各地的每个故事中都可以使用。

dojqjjoe

dojqjjoe5#

如果您想对单个组件执行此操作,而不是全局执行此操作,那么在story文件中,将组件 Package 在内存路由器中。
例如,我有一个包含Link元素的header组件,因此在我的header.stories.tsx文件中,我将更改以下内容:

const Template: ComponentStory<typeof Header> = (args) => (
    <Header {...args} />
);

const Template: ComponentStory<typeof Header> = (args) => (
  <MemoryRouter>
    <Header {...args} />
  </MemoryRouter>
);
0sgqnhkj

0sgqnhkj6#

问题是Storybook渲染单个故事。在本例中,使用<Link>的组件实际上在<Router>之外渲染。
解决方案是使用addDecorator用<Router> Package 各个故事;

//config.js
//...
addDecorator(story => <Router>{story()}</Router>);
flvlnr44

flvlnr447#

如果您还想使用路由路径参数,您将需要使用故事书装饰器。用户Web-skisidonaldson已经展示了如何将路由器模拟添加到故事书中。
下面是我在react v18中实现的故事书路由器模拟

预览.js文件

import { withRouter } from "storybook-addon-react-router-v6";

export const decorators = [withRouter];

组件. story.js文件

import Component from "./component";

export default {
  component: Component,
  title: "component with rout path and parameters",
  parameters: {
    reactRouter: {
      routePath: "/root/:primary/:secondary",
      routeParams: { primary: "firstparam", secondary: "secondparam" },
    },
  },
};

const Template = (args) => <Component {...args} />;

export const Default = Template.bind({});
Default.args = {
// ommited
};

这将为useParams之类的函数提供以下结果:

const {primary, secondary} = useParams();
console.log('primary value: ' + primary)
console.log('secondary value: ' + secondary)
// outputs: primary value: firstparam
// outputs: secondary value: secondparam

相关问题