使用 Typescript 不允许 React createContext(null)?

Posted

技术标签:

【中文标题】使用 Typescript 不允许 React createContext(null)?【英文标题】:React createContext(null) not allowed with Typescript? 【发布时间】: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 没有被定义。

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

【问题讨论】:

【参考方案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>
  )

... 

【讨论】:

以上是关于使用 Typescript 不允许 React createContext(null)?的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 中的 useParams 不允许解构

允许typescript编译器仅在一个react状态属性上调用setState

react native 可以使用typescript开发吗

使用类型别名与接口在 Typescript 中注释 React 功能组件

Typescript React:访问组件属性类型

Typescript:React Context 高阶组件类型错误