Для initialState
вы хотите определить ту же структуру / форму, что и в AppProvider
, так как TypeScript выводит весь тип контекста из заданного начального значения. Таким образом, тип исходного значения определяет форму контекста, которую могут использовать компоненты-потребители.
В вашем примере значение контекста AppProvider
несовместимо с initialState
. Также initialState
типы слишком широки, чтобы быть полезными для потребления компонентов. Например, Object
будет означать, что вы ожидаете, что конструктор Object будет state
(не совсем то, что вы хотите). При setState: () => {}
компоненты, использующие контекст, не смогут вызывать эту функцию с аргументом состояния, так как тип функции претендует на отсутствие параметров.
Здесь я предполагаю, что общее состояние должно выглядеть следующим образом (и опустите дополнительную оболочку массива, которую вы использовали в AppProvider
):
{ isMenuOpen: boolean; isSideOpen: boolean }
Тогда начальное состояние с правильными типами будет:
const initialState = {
// your state defaults
state: { isMenuOpen: false, isSideOpen: false },
// noop
setState: (state: { isMenuOpen: boolean; isSideOpen: boolean }) => {}
};
AppProvider
:
export const AppProvider = (props: IProviderProps) => {
const [state, setState] = useState({ isMenuOpen: false, isSideOpen: false });
return (
<AppContext.Provider value={{ state, setState }}>
{props.children}
</AppContext.Provider>
);
};
Если вы хотите иметь чистый способ с собственным типом состояния и использовать тип React в useState
, вы можете реализовать его следующим образом:
import { createContext, useState, Dispatch, SetStateAction } from "react";
type MyState = {
isMenuOpen: boolean;
isSideOpen: boolean;
};
type ContextValue = {
state: MyState;
// the type when you hover over setState in AppProvider
setState: Dispatch<SetStateAction<MyState>>;
};
const initialState: ContextValue = {
// your state defaults
state: { isMenuOpen: false, isSideOpen: false },
// noop
setState: (state: { isMenuOpen: boolean; isSideOpen: boolean }) => {}
};
Sample