我有一个场景,我被迫调用一个触发器方法来显示来自两个不同地方的模态,一个使用热键组合,另一个通过单击工具栏按钮。为了做到这一点,我有以下代码,其中我调用triggerCustomLinkModal
来设置状态,但随后我被Invalid Hook call error
击中。
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()
}
从Chris在评论中的回答扩展(你不能在React组件外使用钩子。→所以你不能在triggerCustomLinkModal
内部调用useLocalState()
,因为triggerCustomLinkModal
不是一个React组件):
你真的不需要useCallback钩子,甚至不需要函数本身。根据react docs:
注意
React保证setState函数标识是稳定的在重新渲染时更改。这就是为什么从useEffect中省略它是安全的或useCallback依赖项列表。
这也意味着使用useCallback
钩子来设置状态实际上没有意义(因为useCallback角色只是返回a memoized callback
)
你基本上需要的是在最近的父组件中设置一个状态,并将setIsShown
作为prop以及isShown
函数传递。
您当前的实现,即使它不是错误,它也不会引用相同的状态,因为在每个useLocalState()
上,您正在初始化一个新的状态(因此您不指向CustomLinkModalUI
和triggerCustomLinkModal
中的相同状态)