在typescript中使用带有react-hooks的react上下文

IT技术 reactjs typescript react-context react-hooks
2021-05-19 05:39:06

下面的代码演示了我如何尝试使用 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; setPassword:(密码:字符串)=> 无效;}; }' 不能分配给类型 '{ email: string; 密码:字符串;}'。对象字面量只能指定已知属性,并且类型 '{ email: string; 中不存在 'authState'。密码:字符串;}'。[2322] index.d.ts(266, 9):预期的类型来自属性“value”,该属性在此处声明为“IntrinsicAttributes & ProviderProps<{ email: string; 密码:字符串;}>' (property) authState: { email: string; 密码:字符串;}

2个回答

上面的答案有效,因为禁用了严格的类型检查规则。具有严格规则的上下文示例:

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 };

这个对我有用。ThemeLanguage它只是枚举,如下所示:

export enum Theme {
  DEFAULT = 'DEFAULT',
  BLACK = 'BLACK',
}

我送误差函数setContextinitialContext投掷错误,如果程序员没有定义setContextProvider你可以使用

setContext: (): void => {}

祝你好运!

在创建 Context 时,您为其提供了一个初始值。以与您期望的 Provider 格式相同的格式提供它,例如:

const initialState = {
  authState : { 
      email: '',
      password: ''
  },
  authActions = {
    setEmail: () => {},
    setPassword: () => {}
  };
};

const AuthCtx = createContext(initialState);

此外,您甚至不需要 initialState,因为它只传递给 Consumer,如果您在 Consumer 的层次结构中没有更高的 Provider。