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

Ilj*_*lja 4 typescript reactjs react-context react-hooks

下面的代码演示了我如何尝试使用react钩子实现react的上下文,这里的想法是我将能够从任何这样的子组件轻松访问上下文

const {authState, authActions} = useContext(AuthCtx);
Run Code Online (Sandbox Code Playgroud)

首先,我创建一个导出上下文和提供程序的文件。

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;
Run Code Online (Sandbox Code Playgroud)

这行得通,但是我在valueprovider的下面输入了错误,可能是因为我在其中添加了操作,因此出现了问题,我是否有办法保持所有输入的类型,并且仍然能够导出上下文和provider?

我相信,我也无法createContext放入主函数,因为它会一直重新创建它?

[ts]键入'{authState:{email:string; 密码:字符串;}; authActions:{setEmail:(email:string)=> void; setPassword:(密码:字符串)=>无效; }; }'不可指定为'{email:string; 密码:字符串;}'。对象文字只能指定已知的属性,而'authState'在类型'{email:string; 密码:字符串;}'。[2322] index.d.ts(266,9):期望的类型来自属性'value',该属性在此处声明为'IntrinsicAttributes&ProviderProps <{email:string; 密码:字符串;}>'(属性)authState:{电子邮件:字符串;密码:字符串;}

Ром*_*нов 21

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

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 };
Run Code Online (Sandbox Code Playgroud)

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

export enum Theme {
  DEFAULT = 'DEFAULT',
  BLACK = 'BLACK',
}
Run Code Online (Sandbox Code Playgroud)

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

setContext: (): void => {}

祝你好运!


Shu*_*tri 9

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

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

const AuthCtx = createContext(initialState);
Run Code Online (Sandbox Code Playgroud)

另外,如果您没有在Consumer层次结构中位于更高层的Provider,则甚至不需要initialState,因为initialState仅传递给了Consumer。

  • 当我在上下文中使用 usestate 时,我看到此错误。类型 'Dispatch&lt;any&gt;' 不可分配给类型 '() =&gt; void (2认同)