我写了这个小小的React钩子:
type Callback = () => void
function useElementEffect<T extends Element>(callback: (el: T) => (Callback | void)) {
let cb: Callback | void
return useCallback((el: T) => {
if(el) {
cb = callback(el) // <-- eslint error here
} else if(cb) {
cb()
}
}, [])
}
您可以像这样使用它:
function CenterCanvas() {
const [[width, height], setSize] = useState([300, 150])
const ref = useElementEffect((div: HTMLDivElement) => {
const obs = new ResizeObserver(entries => {
for(const entry of entries) {
const contentBoxSize = entry.contentBoxSize[0]
setSize([
Math.floor(contentBoxSize.inlineSize),
Math.floor(contentBoxSize.blockSize)
])
}
})
obs.observe(div)
return () => obs.disconnect()
})
return (
<$Center ref={ref}>
<TheCanvas width={width} height={height}/>
</$Center>
)
}
它运行得很好,但在cb = callback(el)
行上出现ESLint错误:
ESLint:从React Hook useCallback内部对"cb"变量的赋值将在每次呈现后丢失。若要长期保留该值,请将其存储在useRef Hook中,并将可变值保留在."current"属性中。否则,可以直接将此变量移动到useCallback内部。(react-hooks/exhautive-deps)
然而,当CenterCanvas
被卸载时,cb()
的调用似乎非常好,没有错误,所以cb
似乎有足够长的时间被调用,即使它在下一次渲染时再次被覆盖(我希望如此)。
我应该忽略这个警告,还是有一些情况下,这不会工作?
1条答案
按热度按时间qlzsbp2j1#
useCallback
会记住您的回调,并且没有声明的依赖项([]
),您的回调会捕获cb
变量,因此它适用于您的情况。如果你要更新你的自定义钩子来接受一个依赖项数组,那么它会被破坏,所以我建议你按照
eslint
的建议使用一个ref。