添加 Redux 存储后 Storybook 无法工作

问题描述 投票:0回答:1

我已将 Redux 添加到我的 React 应用程序中,但现在无法让 Storybook 工作。我将它包装在

Provider
中并做了一个模型商店,但现在我收到一条错误,提示“无法读取未定义的属性(读取“地图”)”

这是 ReverseStringResults.jsx 的代码

import React from "react";
import { StringResult } from "../StringResult/StringResult";
import { selectStringResults } from "../../redux/reverseStringSlice";
import { useSelector } from "react-redux";

export const ReverseStringResults = () => {
  const stringResults = useSelector(selectStringResults);
  console.log(stringResults)

  return (
    <div>
      <h1>Reverse String Results</h1>
      <ol className="list-group list-group-numbered">
        {stringResults.map((stringResult) => {
          return (
            <StringResult
              key={stringResult.originalString}
              stringResult={stringResult}
            />
          );
        })}
      </ol>
    </div>
  );
};

这是

ReverseStringResults.stories.jsx
的代码:

import React from "react";
import { ReverseStringResults } from "./ReverseStringResults";
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";

export default {
  title: "Components/ReverseStringResults",
  component: ReverseStringResults,
};

// Mock up our Redux store
const store = {
  getState: () => {
    return {
      stringResults: [],
    };
  },
  subscribe: () => 0,
};

const Template = (args) => (
  <Provider store={store}>
    <Router>
      <div>
        <ReverseStringResults {...args} />
      </div>
    </Router>
  </Provider>
);

export const Default = Template.bind({});
Default.args = {
  stringResults: [
    {
      originalString: "Hello World",
      reversedString: "dlroW olleH",
      isPalindrome: false,
    },
    {
      originalString: "kayak",
      reversedString: "kayak",
      isPalindrome: true,
    },
    {
      originalString: "my gym",
      reversedString: "myg ym",
      isPalindrome: true,
    },
    {
      originalString: "Love React",
      reversedString: "tcaeR evoL",
      isPalindrome: false,
    },
    {
      originalString: "mom",
      reversedString: "mom",
      isPalindrome: true,
    },
  ],
};
javascript redux react-redux store storybook
1个回答
0
投票

不要尝试创建模拟“存储”,只需创建并使用实际的 Redux 存储。

导入您的应用程序使用的同一商店对象:

import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";
import { ReverseStringResults } from "./ReverseStringResults";

// Import regular App store
import store from "../path/to/store";

export default {
  title: "Components/ReverseStringResults",
  component: ReverseStringResults,
};

const Template = (args) => (
  <Provider store={store}>
    <Router>
      <div>
        <ReverseStringResults {...args} />
      </div>
    </Router>
  </Provider>
);

或者导入你的根减速器并在故事中创建商店:

import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { configureStore } from "@reduxjs/toolkit";
import { Provider } from "react-redux";
import { ReverseStringResults } from "./ReverseStringResults";
import rootReducer from "../path/to/rootReducer";

export default {
  title: "Components/ReverseStringResults",
  component: ReverseStringResults,
};

// Create Redux store
const store = configureStore({
  reducer: rootReducer,
  preloadedState: { // <-- only if you need specific state for stories
    stringResults: [
      {
        originalString: "Hello World",
        reversedString: "dlroW olleH",
        isPalindrome: false,
      },
      {
        originalString: "kayak",
        reversedString: "kayak",
        isPalindrome: true,
      },
      {
        originalString: "my gym",
        reversedString: "myg ym",
        isPalindrome: true,
      },
      {
        originalString: "Love React",
        reversedString: "tcaeR evoL",
        isPalindrome: false,
      },
      {
        originalString: "mom",
        reversedString: "mom",
        isPalindrome: true,
      },
    ],
  },
});

const Template = (args) => (
  <Provider store={store}>
    <Router>
      <div>
        <ReverseStringResults {...args} />
      </div>
    </Router>
  </Provider>
);

为了避免在必要时创建 Redux 存储提供程序组件,您可以创建一个装饰器函数。

这是一个示例实现:

import React from 'react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from 'reducers';

const withRedux = (Story, context) => {
  const {
    parameters: { redux: { preloadedState } = {} },
  } = context;

  const mockedStore = configureStore({
    reducer: rootReducer,
    preloadedState,
  });

  return (
    <Provider store={mockedStore}>
      <Story />
    </Provider>
  );
};

export default withRedux;

在您的

preview.js
文件中添加以下
decorators
导出。所有故事现在都将提供一个默认的 Redux 存储。

import { withRedux } from '../src/stories/decorators';

...

export const decorators = [withRedux];

在任何需要为故事提供特定状态的故事中,您可以为参数提供

redux.preloadedState
值。

export default {
  title: "Components/ReverseStringResults",
  component: ReverseStringResults,
  // decorators: [withRedux], // <-- use this if you don't use the global decorators
  parameters: {
    redux: {
      preloadedState: {
        stringResults: [
          {
            originalString: "Hello World",
            reversedString: "dlroW olleH",
            isPalindrome: false,
          },
          {
            originalString: "kayak",
            reversedString: "kayak",
            isPalindrome: true,
          },
          {
            originalString: "my gym",
            reversedString: "myg ym",
            isPalindrome: true,
          },
          {
            originalString: "Love React",
            reversedString: "tcaeR evoL",
            isPalindrome: false,
          },
          {
            originalString: "mom",
            reversedString: "mom",
            isPalindrome: true,
          },
        ],
      },
    },
  },
};

const Template = (args) => (
  <Router>
    <div>
      <ReverseStringResults {...args} />
    </div>
  </Router>
);

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

或者为每个故事提供特定的初始状态:

export default {
  title: "Components/ReverseStringResults",
  component: ReverseStringResults,
};

const Template = (args) => (
  <Router>
    <div>
      <ReverseStringResults {...args} />
    </div>
  </Router>
);

export const Default = Template.bind({});
Default.parameters= {
  redux: {
    preloadedState: {
      stringResults: [
        {
          originalString: "Hello World",
          reversedString: "dlroW olleH",
          isPalindrome: false,
        },
        {
          originalString: "kayak",
          reversedString: "kayak",
          isPalindrome: true,
        },
        {
          originalString: "my gym",
          reversedString: "myg ym",
          isPalindrome: true,
        },
        {
          originalString: "Love React",
          reversedString: "tcaeR evoL",
          isPalindrome: false,
        },
        {
          originalString: "mom",
          reversedString: "mom",
          isPalindrome: true,
        },
      ],
    },
  },
};
© www.soinside.com 2019 - 2024. All rights reserved.