【问题标题】:How to initialise the set function of useState for TypeScript in a createContext?如何在createContext中为TypeScript初始化useState的set函数?
【发布时间】:2020-06-27 22:57:38
【问题描述】:

我有一个Provider,它通过两个contexts 提供一个状态变量及其对应的setter。

const BookedBatchContext = createContext({})
const SetBookedBatchContext = createContext(null)

const initialState = {
  id: null
}

Provider 看起来像这样:

export const BookedBatchProvider = ({ children }: { children: any }) => {
  const [bookedBatch, setBookedBatch] = useState(localState ||initialState)

  return (
    <SetBookedBatchContext.Provider value={setBookedBatch}>
      <BookedBatchContext.Provider value={bookedBatch}>
        { children }
      </BookedBatchContext.Provider>
    </SetBookedBatchContext.Provider>
  )
}

通过自定义钩子,我使 setBookedBatch 可用于其他组件:

export const useBookedBatch = () => {
  const bookedBatch = useContext(BookedBatchContext)
  const setBookedBatch = useContext(SetBookedBatchContext)

  return { bookedBatch, setBookedBatch }
}

当尝试使用 setBookedBatch 函数时,我在给定组件中收到以下错误:

setBookedBatch(selectedBatch)

错误:

TS2721: Cannot invoke an object which is possibly 'null'.

由于useState函数的setter是我没有创建的函数,所以创建上下文的时候不知道怎么初始化:

const SetBookedBatchContext = createContext(null)

这样 TypeScript 就不会抱怨了。

  1. 如何知道setter函数的初始值?
  2. 如果我不提供任何类型,如何避免 TS 抱怨 null 值?

【问题讨论】:

    标签: reactjs typescript react-hooks use-state


    【解决方案1】:

    React.createContextReact.useState 的返回类型由您传入的初始值推断确定。

    1.) 您可以通过手动指定泛型类型来创建正确的上下文类型:

    const SetBookedBatchContext = createContext<null | React.Dispatch<React.SetStateAction<State>>>(null)
    

    注意:useState 的 setter 类型为 React.Dispatch&lt;React.SetStateAction&lt;State&gt;&gt;,其中 StatelocalState || initialState 的任何类型。

    2.) 在您的自定义 Hook useBookedBatch 中断言,setBookedBatch 不是 null

    export const useBookedBatch = () => {
      const bookedBatch = useContext(BookedBatchContext)
      const setBookedBatch = useContext(SetBookedBatchContext)
      if (setBookedBatch === null) throw new Error() // this will make setBookedBatch non-null
      return { bookedBatch, setBookedBatch }
      // returns: { bookedBatch: {}; setBookedBatch: React.Dispatch<React.SetStateAction<State>>; }
    }
    

    3.) 然后setBookedBatch 可以在以后调用而无需断言:

    const App = () => {
      const { setBookedBatch } = useBookedBatch()
      useEffect(() => { setBookedBatch({ id: "foo" }) }, [])
    }
    

    Sample on the playground

    【讨论】:

    • 非常感谢。您能否指出我可以找到 React.dispatch 类型的文档? (createContext>>(null))
    • 我找不到,我总是在 redux 文档中结束
    • 你可以在DefinitelyTyped @types/react上找到useStateReact.Dispatch的类型
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 2019-03-08
    • 1970-01-01
    • 2021-10-02
    相关资源
    最近更新 更多