我尝试使用useContext钩子将state和setState传递给一个子组件,但是当我尝试在provider的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; }>'
我如何设置初始状态以允许我传递state和useState变量?
2条答案
按热度按时间hjzp0vay1#
类型脚本从给定的
initialState
到createContext
推断AppContext
类型。AppContext.Provider
需要一个与上述类型匹配的value
属性。因此,由createContext
示例化的类型确定了使用组件可以使用的上下文形状。哪里出了问题?
initialState
获取以下推断类型:将
Object
传递给state
意味着,你期望的是ObjectConstructor
--而不是你真正想要的。对于setState: () => {}
,组件不能用state
参数调用这个函数。还请注意,useState
初始值当前被 Package 在一个额外的数组[{...}]
中。总之,
[state, setState]
参数与AppContext.Provider
值属性不兼容。溶液
我们假设,您想要的状态形状如下所示:
则具有适当类型的初始状态是(playground):
具有自己的上下文值类型(playground)的更显式的变体:
讨论其他选择
完全删除上下文默认值(playground)
为了防止客户端现在必须检查
undefined
,请提供一个自定义Hook:切换到
useReducer
和/或自定义useAppContext
挂钩考虑用
useReducer
替换useState
,并将dispatch
函数传递给组件,这将提供更好的封装,因为状态操作逻辑现在集中在一个纯Reducer中,子组件 * 不能 * 再通过setState
直接操作它。另一个将UI逻辑从域逻辑中分离出来的好方法是提供一个自定义的
useAppContext
Hook,而不是使用useContext(AppContext)
--参见前面的示例。现在useAppContext
可以提供一个更窄的API,而无需发布整个上下文。rqenqsqc2#
在我看来,一个令人满意且简单的解决方案是创建一个额外的函数,它可以setState。