Пробуем работать с context
/ hooks
и TypeScript
впервые. Поскольку я отправляю значение и функцию (функция отправки / установки), я использую шаблон разделения Provider
, описанный в этого сообщения в блоге под заголовком «Шаблон B - A Разделение ".
Следующая настройка работает должным образом, пока я экспортирую свои объекты 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>
);
}