开发者问题收集

尝试设置状态时出现无效的钩子调用错误

2022-06-22
88

我遇到一种情况,我被迫从两个不同的地方调用触发器方法来显示模态框,一个地方使用热键组合,另一个地方通过单击工具栏按钮。为了做到这一点,我有以下代码,其中我调用 triggerCustomLinkModal 来设置状态,但随后我遇到了 无效钩子调用错误

import { useState, useCallback, useEffect } from "react"
import { Dialog } from "@blueprintjs/core"

const useLocalState = () => {
  const [isShown, setIsShown] = useState(false)

  const setState = useCallback((state) => {
    setIsShown(state)
  })

  const getState = useCallback(() => {
    return isShown
  })

  return {
    setState,
    getState
  }
}

export const CustomLinkModalUI = () => {
  const { getState } = useLocalState()

  return (
    <>
      <Dialog isOpen={getState()} />
    </>
  )
}

export const triggerCustomLinkModal = () => {
  const { setState } = useLocalState()

  setState()
}
1个回答

从评论中的 Chris 的回答扩展(您不能在 React 组件 之外使用钩子。-> 因此您无法在 triggerCustomLinkModal 内部调用 useLocalState() ,因为 triggerCustomLinkModal 不是 React 组件):

您实际上并不需要 useCallback 钩子,甚至不需要函数本身。根据 react docs :

Note

React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.

这也意味着使用 useCallback 钩子来设置状态实际上没有任何意义(因为 useCallback 的作用只是返回 记忆化回调

您基本上需要的是在最近的父组件中设置状态,并传递 setIsShown 作为 prop 以及 isShown 函数。

您当前的实现,即使没有错误,它也不会引用相同的状态,因为在每个 useLocalState() 上您都在初始化一个全新的状态(因此您不是在指向相同的状态 CustomLinkModalUItriggerCustomLinkModal )

Berci
2022-06-22