在打字稿中使用反应上下文和反应钩子
Using react context with react hooks in typescript
下面的代码演示了我如何尝试使用反应钩子来实现反应的上下文,这里的想法是我将能够像这样轻松地从任何子组件访问上下文
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] Type '{ authState: { email: string; password: string; };
authActions: { setEmail: (email: string) => void; setPassword:
(password: string) => void; }; }' is not assignable to type '{ email:
string; password: string; }'. Object literal may only specify known
properties, and 'authState' does not exist in type '{ email: string;
password: string; }'. [2322] index.d.ts(266, 9): The expected type
comes from property 'value' which is declared here on type
'IntrinsicAttributes & ProviderProps<{ email: string; password:
string; }>' (property) authState: {
email: string;
password: string; }
创建上下文时,您正在为其提供初始值。以与您期望的提供者相同的格式提供它,例如:
const initialState = {
authState : {
email: '',
password: ''
},
authActions = {
setEmail: () => {},
setPassword: () => {}
};
};
const AuthCtx = createContext(initialState);
此外,您甚至不需要 initialState,因为它只传递给消费者,如果您在消费者的层次结构中没有更高级别的提供者。
上面的答案有效,因为严格的类型检查规则被禁用。
具有严格规则的上下文示例:
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
中发送错误函数以抛出错误。你可以只使用
setContext: (): void => {}
祝你好运!
下面的代码演示了我如何尝试使用反应钩子来实现反应的上下文,这里的想法是我将能够像这样轻松地从任何子组件访问上下文
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] Type '{ authState: { email: string; password: string; }; authActions: { setEmail: (email: string) => void; setPassword: (password: string) => void; }; }' is not assignable to type '{ email: string; password: string; }'. Object literal may only specify known properties, and 'authState' does not exist in type '{ email: string; password: string; }'. [2322] index.d.ts(266, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & ProviderProps<{ email: string; password: string; }>' (property) authState: { email: string; password: string; }
创建上下文时,您正在为其提供初始值。以与您期望的提供者相同的格式提供它,例如:
const initialState = {
authState : {
email: '',
password: ''
},
authActions = {
setEmail: () => {},
setPassword: () => {}
};
};
const AuthCtx = createContext(initialState);
此外,您甚至不需要 initialState,因为它只传递给消费者,如果您在消费者的层次结构中没有更高级别的提供者。
上面的答案有效,因为严格的类型检查规则被禁用。 具有严格规则的上下文示例:
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
中发送错误函数以抛出错误。你可以只使用
setContext: (): void => {}
祝你好运!