storybook-react-context
在 Storybook 內操作 React 內容。從 React 元件外部讀取狀態並發送更新。
安裝
npm install -D storybook-react-context
使用方式
在需要的地方新增 withReactContext
裝飾器,可針對單一元件或全域套用。
import { withReactContext } from 'storybook-react-context';
export default {
title: 'some story',
decorators: [withReactContext],
};
裝飾器也可以預先設定用於模組中的所有 Story
export default {
title: 'some story',
decorators: [
withReactContext({
context: ExampleContext,
contextValue: { authenticated: false },
}),
],
};
或者透過參數
export default {
title: 'some story',
decorators: [withReactContext],
parameters: {
reactContext: {
context: ExampleContext,
contextValue: { authenticated: false },
},
},
};
注意:避免對 reactContext
使用與 Story 預設匯出中相同的 context
參數。這會導致超出最大呼叫堆疊大小的錯誤。
選項
withReactContext
接受一個參數,該參數是一個物件,具有以下可選屬性
context
- 由React.createContext
傳回的內容,用於為 Story 的元件提供。contextValue
- 用於提供者的值。如果提供了函式,則會以 Story 內容作為第一個引數呼叫該函式。該函式可以傳回 React Hook,例如useState
或useReducer
,以管理 Story 定義中的狀態。contexts
- 一個內容選項陣列(一個具有context
和contextValue
屬性的物件),用於為 Story 的元件提供多個內容。
裝飾器選項也可以使用 reactContext
鍵在 Story 參數中設定。
export default {
title: 'My Component',
component: MyComponent,
decorators: [withReactContext],
};
// single provider is used for `MyComponent`
const SomeStory = {
parameters: {
reactContext: {
context: FirstContext,
contextValue: { someContextValue: true },
},
},
}
// multiple provider are used wrapping the `MyComponent` component
const AnotherStory = {
parameters: {
reactContext: {
contexts: [
{
context: FirstContext,
contextValue: { someContextValue: true },
},
{
context: SecondContext,
contextValue: [1, 2, 3],
}
]
},
},
}
元件或 render 函式的結果將使用提供者包裝,並將值設定為 contextValue
的結果。內容值會透過 Story 內容(第二個引數)中的 reactContext
屬性傳回給 Story 的 render 函式。該屬性包含兩個屬性:values
和 value
。values
屬性是為每個內容提供的所有值的陣列。value
屬性會傳回最後一個值,對於單一內容很有用。
import * as React from 'react';
import { withReactContext } from 'storybook-react-context';
const reducer = (state, action) => ({ ...state, ...action });
// the values are arrays as we expect a setter/dispatch function as second argument in some of the stories
const FirstContext = React.createContext([{ text: 'Initial text' }]);
const SecondContext = React.createContext(['black']);
const MyComponent = () => {
const [textState] = React.useContext(FirstContext);
const [colorState] = React.useContext(SecondContext);
return <div style={{ color: colorState }}>{textState?.text}</div>;
};
export default {
title: 'My Component',
component: MyComponent,
decorators: [withReactContext],
};
// access the reducer dispatch function set in the contextValue parameter from the story
export const FirstStory = {
render: (_, { reactContext }) => {
const [, dispatch] = reactContext.value;
return (
<>
<MyComponent />
<button onClick={() => dispatch({ text: 'Changed text' })}>Change text</button>
</>
);
},
parameters: {
reactContext: {
context: FirstContext,
contextValue: () => React.useReducer(reducer, { text: 'Initial text' }),
},
},
};
// apply multiple contexts and use `reactContext.values` to access the setters from the story
export const SecondStory = {
render: (_, { reactContext }) => {
const [, [color, setFirstContextValue]] = reactContext.values;
const colors = ['red', 'orange', 'blue', 'green', 'purple'];
return (
<>
<MyComponent />
<p>Selected color: {color}</p>
<button
onClick={() => {
const randomColor = colors[Math.floor(Math.random() * colors.length)];
return setFirstContextValue(randomColor);
}}
>
Toggle Value
</button>
</>
);
},
parameters: {
reactContext: {
contexts: [
{
context: FirstContext,
contextValue: [{ text: 'New text' }],
},
{
context: SecondContext,
contextValue: () => React.useState(),
},
],
},
},
};
// use story controls (args) to set the context value
export const ThirdStory = {
args: { text: 'Initial text' },
parameters: {
reactContext: {
context: FirstContext,
contextValue: ({ args }) => [
{
text: args.text,
},
],
},
},
};
contextValue
函式會提供 Story 內容作為其第一個引數。這會提供對 Story args 和其他內容值的存取。此外,來自 @storybook/preview-api
的 useArgs Hook 可用於存取和更新 Story 內的 args。
如需更多資訊,請參閱範例 Story。