【问题标题】:How to use redux-toolkit with Storybook?如何在 Storybook 中使用 redux-toolkit?
【发布时间】:2021-07-26 07:47:24
【问题描述】:

我目前正在尝试使用 Storybook 设置 redux-toolkit。但是,当我在故事书中查看它们时,我的选择器在我的组件中返回未定义。当我将我的应用程序作为普通的 React 应用程序运行时,选择器会返回适当的状态。

如何使用 Redux 设置 Storybook,以便我的选择器实际上从商店返回预期状态?

这是我的故事书故事:

import { Meta, Story } from "@storybook/react"
import ContactInfo from "./ContactInfo"
import { Provider } from "react-redux"
import { store } from "../../../store/config/configureStore"

export default {
  title: "Forms/ContactInfo",
  component: ContactInfo,
  decorators: [(story) => <Provider store={store}>{story()}</Provider>],
} as Meta

export const Template: Story<{}> = (args) => <ContactInfo {...args} />

这是我的商店配置

import { configureStore } from "@reduxjs/toolkit"
import { useDispatch } from "react-redux"
import { logger } from "../middleware/logger"
import rootReducer from "./reducer"

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false,
      immutableCheck: false,
    }).concat(logger),
})

export { store }

export type AppDispatch = typeof store.dispatch
export const useAppDispatch = () => useDispatch<AppDispatch>()

export type RootState = ReturnType<typeof rootReducer>

export interface GetState {
  getState: () => RootState
}

这是我的带有选择器的组件

import React from "react"
import { useSelector } from "react-redux"
import { useAppDispatch } from "../../../store/config/configureStore"
import {
  selectContactInfo,
  updateContactInfo,
} from "../../../store/contactInfo"
import Social from "../../components/social/Social"
import TextField from "../../components/textField/TextField"

export default function ContactInfo() {
  const dispatch = useAppDispatch()
  const contactInfo = useSelector(selectContactInfo)

  console.log("printing contactInfo", contactInfo)

  const handleChange = (event: any) => {
    const target = event.target

    const updatedContactInfo = { ...contactInfo, [target.name]: target.value }
    dispatch(updateContactInfo(updatedContactInfo))
  }

  const handleSubmit = (event: React.SyntheticEvent) => {
    console.log("User submitted contact info section: ", contactInfo, "yo")
    event.preventDefault()
  }

  return (
    <form onSubmit={handleSubmit}>
      <h2>Enter Your Contact Information</h2>
      <TextField
        label="First Name"
        value={contactInfo.firstName}
        onChange={handleChange}
      />

      <TextField
        label="Last Name"
        value={contactInfo.lastName}
        onChange={handleChange}
      />

      <TextField
        label="Middle Initial"
        value={contactInfo.middleInitial}
        onChange={handleChange}
        required={false}
        maxLength={1}
      />

      <TextField
        label="Email Address"
        type="email"
        value={contactInfo.emailAddress}
        onChange={handleChange}
      />

      <Social socialLinks={contactInfo.socialLinks} />

      <TextField
        label="Phone Number"
        type="tel"
        value={contactInfo.phoneNumber}
        onChange={handleChange}
      />

      <button
        type="button"
        onClick={() => console.log("User wants to go back.")}
      >
        Back
      </button>
      <button type="submit">Next</button>
    </form>
  )
}

【问题讨论】:

    标签: storybook redux-toolkit


    【解决方案1】:

    要解决此问题,请在您的 .storybook/preview.js 文件中添加一个全局装饰器:

    import { Provider } from "react-redux"
    import { store } from "../src/store/config/configureStore"
    
    export const parameters = {
      actions: { argTypesRegex: "^on[A-Z].*" },
      controls: {
        matchers: {
          color: /(background|color)$/i,
          date: /Date$/,
        },
      },
    }
    
    export const decorators = [
      (Story) => (
        <Provider store={store}>
          <Story />
        </Provider>
      ),
    ]
    
    

    2021 年 11 月 26 日更新

    通过.storybook/preview.js 添加提供程序(或模拟它)实际上是一个好习惯

    As showed in the storybook's screen tutorial

    【讨论】:

      【解决方案2】:

      如上所述,您可以通过 Provider 将您的 redux 存储连接到您的 Story 组件。但实际上这种做法是错误的。

      为设计组件而创建的故事书,独立构建您的 UI(如其主页所述)。 不适用于测试商店交互。逻辑和从存储接收数据应该分开放置。当您想在应用程序之外呈现组件时,Storybook 很有用。要测试与 Store 的交互 - 只需使用 react-scripts 或 npm 脚本在应用程序中运行它。

      如果您问这个问题 - 可能您的应用程序设计得很糟糕。我会考虑重构。

      【讨论】:

        猜你喜欢
        • 2021-03-25
        • 2021-04-15
        • 2021-08-02
        • 1970-01-01
        • 1970-01-01
        • 2021-09-21
        • 2019-06-16
        • 2021-02-06
        • 2021-04-14
        相关资源
        最近更新 更多