在打字稿中使用带有React钩子的react上下文

时间:2018-11-16 10:25:48

标签: reactjs typescript react-context react-hooks

下面的代码演示了我如何尝试使用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:{       电子邮件:字符串;       密码:字符串; }

2 个答案:

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

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

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

如果程序员没有在setContext中定义initialContext,我就在setContext内部Provider中发送Error函数,以抛出错误。您只能使用

setContext: (): void => {}

祝你好运!