下面的代码演示了我如何尝试用react钩子实现react的上下文,这里的想法是我将能够轻松地从任何子组件访问上下文,比如这个
const {authState, authActions} = useContext(AuthCtx);
首先,我创建了一个导出上下文和提供程序的文件。
import * as React from 'react';
const { createContext, useState } = React;
const initialState = {
email: '',
password: ''
};
const AuthCtx = createContext(initialState);
export function AuthProvider({ children }) {
function setEmail(email: string) {
setState({...state, email});
}
function setPassword(password: string) {
setState({...state, password});
}
const [state, setState] = useState(initialState);
const actions = {
setEmail,
setPassword
};
return (
<AuthCtx.Provider value={{ authState: state, authActions: actions }}>
{children}
</AuthCtx.Provider>
);
}
export default AuthCtx;
这是可行的,但我在提供程序的value
中收到了以下错误,可能是因为我在中添加了操作,因此问题是,有没有一种方法可以让我保持所有内容的类型,并且仍然能够导出上下文和提供程序?
我相信我也不能把createContext
放在我的主函数中,因为它会一直重新创建它?
[ts]类型'{authState:{email:string;password:string!};authActions:{setEmail:(email:string(=>void;setPassword:(密码:string(=>void;};}'不可分配给类型"{email:一串password:string;}'。对象文字只能指定已知属性,并且类型"{email:string;"中不存在"authState";password:string;}'。[2232]index.d.ts(266,9(:所需的类型来自在类型上此处声明的属性"value"'本质属性&ProviderProps<{email:string;密码:string;}>'(property(authState:{电子邮件:字符串;密码:string;}
上面的答案有效,因为禁用了严格的类型检查规则。具有严格规则的上下文示例:
import { createContext, Dispatch, SetStateAction, useState } from 'react';
import { Theme } from '@styles/enums';
import { Language } from '@common/enums';
type Props = {
children: React.ReactNode;
};
type Context = {
appLang: string;
appTheme: string;
setContext: Dispatch<SetStateAction<Context>>;
};
const initialContext: Context = {
appLang: Language.EN,
appTheme: Theme.DEFAULT,
setContext: (): void => {
throw new Error('setContext function must be overridden');
},
};
const AppContext = createContext<Context>(initialContext);
const AppContextProvider = ({ children }: Props): JSX.Element => {
const [contextState, setContext] = useState<Context>(initialContext);
return (
<AppContext.Provider value={{ ...contextState, setContext }}>
{children}
</AppContext.Provider>
);
};
export { AppContext, AppContextProvider };
它对我有效。Theme
和Language
只是枚举,如下所示:
export enum Theme {
DEFAULT = 'DEFAULT',
BLACK = 'BLACK',
}
如果程序员没有在Provider
中定义setContext
,我会在setContext
内部的initialContext
中发送Error函数以引发错误。你可以直接使用
setContext: (): void => {}
祝你好运!
在创建Context时,您正在为其提供初始值。以您期望的格式为提供程序提供该值,如:
const initialState = {
authState : {
email: '',
password: ''
},
authActions = {
setEmail: () => {},
setPassword: () => {}
};
};
const AuthCtx = createContext(initialState);
此外,您甚至不需要initialState,因为它只传递给Consumer,如果您在Consumer的层次结构中没有更高级别的Provider。