9

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

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; 设置密码:(密码:字符串)=> 无效;}; }' 不可分配给类型 '{ email: string; 密码:字符串;}'。对象字面量只能指定已知属性,并且 'authState' 不存在于类型 '{ email: string; 密码:字符串;}'。[2322] index.d.ts(266, 9):预期类型来自属性“值”,该属性在此处声明类型为“IntrinsicAttributes & ProviderProps<{ email: string; 密码:字符串;}>' (property) authState: { email: string; 密码:字符串;}

4

2 回答 2

29

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

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没有setContextProvider. 你可以使用

setContext: (): void => {}

祝你好运!

于 2019-09-12T14:02:07.867 回答
17

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

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

const AuthCtx = createContext(initialState);

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

于 2018-11-16T10:50:26.943 回答