首次尝试使用context
/ hooks
和TypeScript
。因为我要发送值和一个函数(调度/设置函数),所以我使用的是this blog post, under the header "Pattern B - A Separation"中概述的Provider
分离模式。
只要我导出StateContext
和DispatchContext
对象并导入它们以使其与消费组件中的useContext
一起使用,以下设置就会按预期工作。
// src/components/index.tsx
ReactDOM.render(
<Router>
<MyProvider>
<MyComponent />
</MyProvider>
</Router>,
document.getElementById("root")
);
// src/providers/myProvider.tsx
import React, { useState, useContext } from "react";
type MyProviderProps = { children: React.ReactNode };
type State = string | undefined;
type Dispatch = (value: State) => void;
export const StateContext = React.createContext<State>(undefined);
export const DispatchContext = React.createContext<Dispatch | undefined>(undefined);
export function MyProvider({ children }: MyProviderProps) {
const [state, dispatch] = useState<State>(undefined);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
{children}
</DispatchContext.Provider>
</StateContext.Provider>
);
}
// src/components/MyComponent.tsx
import React from "react";
import {
StateContext,
DispatchContext,
} from "../providers/myProvider";
export default function MyComponent() {
const myMessage = React.useContext(StateContext);
const setMyMessage = React.useContext(DispatchContext);
return (
<div>{myMessage}</div>
);
}
但是,如果我尝试为useContext(XyzContext)
创建辅助函数,则会收到错误消息,因为上下文为undefined
:useMyMessage must be used within MyProvider
。我不知道为什么此辅助功能会导致问题。
// src/providers/myProvider.tsx
import React, { useState, useContext } from "react";
type MyProviderProps = { children: React.ReactNode };
type State = string | undefined;
type Dispatch = (value: State) => void;
const StateContext = React.createContext<State>(undefined);
const DispatchContext = React.createContext<Dispatch | undefined>(undefined);
export function MyProvider({ children }: MyProviderProps) {
const [state, dispatch] = useState<State>(undefined);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
{children}
</DispatchContext.Provider>
</StateContext.Provider>
);
}
export function useMyMessage() {
const context = useContext(StateContext);
if (!context) {
throw new Error("useMyMessage must be used within MyProvider");
}
return context;
}
// src/components/MyComponent.tsx
import React from "react";
import {
useMyMessage,
DispatchContext,
} from "../providers/myProvider";
export default function MyComponent() {
const myMessage = useMyMessage();
const setMyMessage = React.useContext(DispatchContext);
return (
<div>{myMessage}</div>
);
}