【问题标题】:React createContext(null) not allowed with Typescript?使用 Typescript 不允许 React createContext(null)?
【发布时间】:2020-11-14 17:25:13
【问题描述】:

我正在尝试使用 useReducer 和 useContext 挂钩设置 React 存储。 React.createContext(defaultValue) 正在使用我的 TS 检查器创建问题。我尝试了一些不同的东西,但本质上,我 createContext(null) 然后在组件 useReducer() 中设置状态和调度,但是当我调用提供者并将值作为 {state, dispatch} 传递时,它没有告诉我“类型'{状态:任何;调度:React.Dispatch;}'不可分配给类型'null'。

我不明白这一点,因为当它出错时,我已经分配了状态和调度,并且值不应再为空。

这是我正在尝试创建的 Context Provider 包装器。

import React, { createContext, useReducer, FC, Dispatch } from 'react';
import storeReducer, { initialState } from './reducer';
import { Action, State } from './types';
import { isNull } from 'util';

const StoreContext = createContext(null);

const StoreProvider:FC = ({ children }) => {
  const [state, dispatch] = useReducer(storeReducer, initialState);
  const value = {state, dispatch}
  return (
    <StoreContext.Provider value={value}>
      {children}
    </StoreContext.Provider>
  );
};

export { StoreProvider, StoreContext };

export interface IStoreContext {
  dispatch: (action: Action<any>) => {};
  state: State;
}

如果我将其保留为简单的 const StoreContext = createContext();,那么它会抱怨 defaultValue 没有被定义。

疯狂的是,我已经从一个旧项目中提取了这个并且编译时没有问题。

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    当您使用null 初始化上下文时,无法推断出预期的类型。在这种情况下,您必须明确给出上下文的类型。

    这里看起来像:

    const StoreContext = createContext<{
      state: MyStateType,
      dispatch: Dispact,
    } | null>(null);
    

    【讨论】:

    • 我试过了。当我声明类型时,我让它工作,但在消费者(我称之为 useContext)中,我收到以下错误:Argument of type 'Context&lt;MyContextType | null&gt;' is not assignable to parameter of type 'Context&lt;MyContextType&gt;'. 我为“MyContextType”创建了一个接口,如下所示:export interface MyContextType { state: State; dispatch: Dispatch&lt;any&gt;; }。这是消费者中的上下文回调:const ctx = useContext&lt;MyContextType&gt;(StoreContext)
    • 它不喜欢 null 在我初始化时作为值,但它也不允许我声明 &lt;TypeName | null&gt;
    【解决方案2】:

    由于我刚刚注册了一个帐户来回答这个问题,我无法在上面发表评论。 Alex Wayne 是正确的,Typescript 可以接受。但是,useContext 钩子并不能真正解决这个问题,因为就 Typescript 而言,您可能在该上下文中有一个 null 值。

    来自原始答案...这是我们在 Typescript 中的上下文 const StoreContext = createContext&lt;{state: MyStateType, dispatch: Dispatch} | null&gt;(null);

    所以,我们需要创建一个新的钩子,我们称之为useContextAndErrorIfNull。这看起来像:

    const useContextAndErrorIfNull = <ItemType>(context: Context<ItemType | null>): ItemType => {
      const contextValue = useContext(context);
      if (contextValue === null) {
        throw Error("Context has not been Provided!");
      }
      return contextValue;
    }
    

    使用这个钩子代替useContext,它应该都能正常工作。

    【讨论】:

    • 完美,当您知道在提供程序未初始化时您将永远不会使用您的上下文时,这非常有用
    【解决方案3】:

    在这种情况下,为了省去麻烦,可以暂时施放它:

    interface Store {
      state: MyStateType,
      dispatch: Dispact,
    }
    
    const StoreContext = createContext<Store>({} as Store);
    
    const StoreProvider = ({children}) => {
      const {state, dispatch} = theseAreAlwaysPresent()
    
      return (
        <StoreContext value={{state, dispatch}}>
          {children}
        </StoreContext.Provider>
      )
    }
    ... 
    
    

    【讨论】:

      猜你喜欢
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 2022-07-09
      相关资源
      最近更新 更多