我正在尝试使用useContext挂钩将状态和setState传递给子组件,但是当我尝试在提供程序的value参数中传递[state,setState]时遇到了ts错误。我的代码如下:
export interface IProviderProps {
children?: any;
}
const initialState = {
state: Object,
setState: () => {},
};
export const AppContext = createContext(initialState);
export const AppProvider = (props: IProviderProps) => {
const [state, setState] = useState([{ isMenuOpen: false, isSideOpen: false }]);
return <AppContext.Provider value={[state, setState]}>{props.children}</AppContext.Provider>;
};
我在设置的initialState
的值变量上遇到错误。
index.d.ts(290, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & ProviderProps<{ state: ObjectConstructor; setState: () => void; }>'
如何设置初始状态以允许我传递状态和useState变量?
答案 0 :(得分:2)
对于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>
);
};
如果您想以自己的状态类型和在useState
中使用过的React类型来获得一种简洁的方式,则可以这样实现:
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 }) => {}
};
答案 1 :(得分:0)
下面是使用TypeScript和hooks的React.Context
的示例实现。
有关更多信息,请参见React - Context。
// Dependencies.
import React, {createContext, useState, SetStateAction, Dispatch} from 'react'
// App Context.
interface AppContext {
// Data.
menuIsOpen: boolean
sideIsOpen: boolean
// Functions.
setMenuIsOpen: Dispatch<SetStateAction<boolean>>
setSideIsOpen: Dispatch<SetStateAction<boolean>>
}
// Context.
export const Context = createContext<AppContext>({
// Data.
menuIsOpen: false,
sideIsOpen: false,
// Functions.
setMenuIsOpen: open => {},
setSideIsOpen: open => {}
})
// Provider
export const Provider: React.FC<{}> = props => {
// State.
const [menuIsOpen, setMenuIsOpen] = useState(false)
const [sideIsOpen, setSideIsOpen] = useState(false)
// Data.
const data = {menuIsOpen, sideIsOpen}
// Functions.
const functions = {setMenuIsOpen, setSideIsOpen}
// Value.
const value = {...data, ...functions}
// ..
return <Context.Provider value={value}>{props.children}</Context.Provider>
}