【问题标题】:Using react context with react hooks in typescript在打字稿中使用带有反应钩子的反应上下文
【发布时间】:2019-04-19 12:38:54
【问题描述】:

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

【问题讨论】:

  • 你在哪里输入你的上下文
  • @ShubhamKhatri 默认情况下它从createContext(initialState) 继承它,问题是创建超出了功能,因此我无法输入我认为的操作。当它们更新状态时,我需要在我的功能组件中执行这些操作。如果我在函数内移动上下文,我可以轻松地输入动作,但不再导出上下文,我认为会有复杂性,因为反应函数组件在每次渲染时都会重新运行

标签: reactjs typescript react-context react-hooks


【解决方案1】:

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

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',
}

如果程序员没有在Provider 中定义setContext,我会在setContext 内部initialContext 中发送错误函数以引发错误。你可以使用

setContext: (): void =&gt; {}

祝你好运!

【讨论】:

  • 这应该标记为正确答案,谢谢。
【解决方案2】:

在创建上下文时,您正在为其提供一个初始值。以与您对 Provider 的预期格式相同的格式提供它,例如:

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

const AuthCtx = createContext(initialState);

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

【讨论】:

  • 当我在上下文中使用 usestate 时,我看到了这个错误。Type 'Dispatch' is notassignable to type '() => void
猜你喜欢
  • 2021-06-30
  • 2023-03-08
  • 2020-12-19
  • 2023-01-20
  • 2023-03-29
  • 1970-01-01
  • 2021-07-09
  • 2021-11-22
  • 2022-01-27
相关资源
最近更新 更多