React useContext & Typescript:不是数组类型

Posted

技术标签:

【中文标题】React useContext & Typescript:不是数组类型【英文标题】:React useContext & Typescript: Not an Array Type 【发布时间】:2021-09-11 17:22:34 【问题描述】:

我使用 React createContext 创建了以下上下文:

import  useBoolean  from "@chakra-ui/react"
import  createContext, FC  from "react"

type useBooleanReturn = ReturnType<typeof useBoolean>

export const MobileContext = createContext<
  [show: useBooleanReturn[0], setShow: useBooleanReturn[1]] | undefined
>(undefined)

// --- PROVIDER
const MobileProvider: FC = ( children ) => 
  const [show, setShow] = useBoolean(false)

  return (
    <MobileContext.Provider value=[show, setShow]>
      children
    </MobileContext.Provider>
  )


export default MobileProvider

据我所知,这可以正常工作(至少我没有收到任何打字稿错误)。

我现在想按如下方式“使用”该上下文:

import * as React from "react"

import MobileProvider,  MobileContext  from "./context.mobile"

const Mobile = () => 
  const [show, setShow] = React.useContext(MobileContext)
  ...


export default Mobile

我在这里遇到了一些打字错误——特别是,[show, setShow] 带有红色波浪线下划线和以下消息:

Type '[
  show: boolean, 
  setShow:  
    readonly on: () => void; 
    readonly off: () => void; 
    readonly toggle: () => void; 
    
  ] | undefined' is not an array type.ts(2461)

我不明白为什么这不是数组类型或如何解决这个问题。

有什么想法吗?

谢谢。

【问题讨论】:

【参考方案1】:

我会这样做

const [show, setShow] = React.useContext(MobileContext) ?? []

这里唯一的问题是showsetShow 可能是未定义的。如果需要,您实际上可以为这些设置默认值:

const [
  show = false,
  setShow = () => ,
] = React.useContext(MobileContext) ?? []

不过,设置默认值可能会混淆showsetShow的类型,例如可以设置show = 1。所以,你知道...负责任地使用。

【讨论】:

【参考方案2】:
export const MobileContext = createContext<
  [show: useBooleanReturn[0], setShow: useBooleanReturn[1]] | undefined
>(undefined)

您已指定虽然值可能是一个数组,但它也可能是undefined。如果这是正确的,那么您将需要在与它交互之前检查 undefined,就好像它是一个数组一样:

const Mobile = () => 
  const value = React.useContext(MobileContext);
  if (value) 
    const [show, setShow] = value;
    // do something with show and setShow
  

另一方面,如果您不希望undefined 成为可能,则更新上下文的初始化:

export const MobileContext = createContext<
  [show: useBooleanReturn[0], setShow: useBooleanReturn[1]]
>([false, () => ])

【讨论】:

我不希望 undefined 成为可能,我只添加它是因为 React Context 需要一个默认值。话虽如此,当我尝试您的解决方案时,() =&gt; 出现不同的错误。即:Type '() =&gt; void' is missing the following properties from type ' readonly on: () =&gt; void; readonly off: () =&gt; void; readonly toggle: () =&gt; void; ': on, off, toggle。知道如何解决这个问题吗? 您需要填写与useBooleanReturn[1] 类型匹配的默认值。我猜了一下可能是什么并做了一个空函数,但显然不匹配。【参考方案3】:

你只是说它可以是未定义的,如果它是未定义的,那么它就不能以这种方式解构。

很容易看出这会引发错误: const [show, setShow] = undefined;

所以要么检查从 useContext 返回的值是否未定义,要么使用虚拟数据对其进行初始化。

【讨论】:

以上是关于React useContext & Typescript:不是数组类型的主要内容,如果未能解决你的问题,请参考以下文章

为啥 `useContext` 不重新渲染我的组件?

React.useContext() 不断返回未定义?

React Context中的useContext解析及使用

React Context中的useContext解析及使用

React:useContext,如何从外部组件中检索它?

React.useContext 没有更新