下面的代码演示了我如何尝试使用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;密码:字符串; }; authActions:{setEmail:(email:string)=> void;设置密码: (密码:字符串)=>无效; }; }'不能分配给类型'{电子邮件: 串;密码:字符串; }'。对象文字只能指定已知 属性,并且'authState'在类型'{email:string; 密码:字符串; }'。 [2322] index.d.ts(266,9):期望的类型 来自属性“值”,其在类型上声明 'IntrinsicAttributes&ProviderProps <{电子邮件:字符串;密码: 串; }>'(属性)authState:{ 电子邮件:字符串; 密码:字符串; }
答案 0 :(得分:4)
在创建Context时,您正在为其提供初始值,以与期望的提供方相同的格式提供它,例如
const initialState = {
authState : {
email: '',
password: ''
},
authActions = {
setEmail: () => {},
setPassword: () => {}
};
};
const AuthCtx = createContext(initialState);
另外,如果您在Consumer层次结构中没有更高的Provider,那么甚至不需要initialState,因为initialState仅传递给Consumer。
答案 1 :(得分:3)
上面的答案行之有效,因为禁用类型检查的严格规则。 具有严格规则的上下文示例:
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',
}
如果程序员没有在setContext
中定义initialContext
,我就在setContext
内部Provider
中发送Error函数,以抛出错误。您只能使用
setContext: (): void => {}
祝你好运!