如何在 Storybook 中使用 redux-toolkit?
Posted
技术标签:
【中文标题】如何在 Storybook 中使用 redux-toolkit?【英文标题】:How to use redux-toolkit with Storybook? 【发布时间】: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>
)
【问题讨论】:
【参考方案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 脚本在应用程序中运行它。
如果您问这个问题 - 可能您的应用程序设计得很糟糕。我会考虑重构。
【讨论】:
以上是关于如何在 Storybook 中使用 redux-toolkit?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Storybook 中使用 redux-toolkit?
如何在 Storybook 中为 Angular 启用样式源映射
如何导出在 storybook 中创建的 React Native 组件以便在实际应用中使用?