如何获得使用refs的自定义钩子的' useEffect '代码重用?



我需要在渲染后提供一些使用refs的自定义功能。

对于useEffect来说,这似乎是一个完美的用例,但它需要在一个自定义钩子中,以便可以重用。

不幸的是,传递一个ref或它的current给一个自定义钩子,使用useEffect似乎会导致不同的行为,而不是直接调用useEffect

一个工作示例如下:

const useCustomHookWithUseEffect = (el1, el2) => {
React.useEffect(() => {
console.log("CUSTOM Use effect...");
console.log("firstRef element defined", !!el1);
console.log("secondRef element", !!el2);
}, [el1, el2]);
}
const RefDemo = () => {
const [vis, setVis] = React.useState(false);

const firstRef = React.useRef(null);
const secondRef = React.useRef(null);

useCustomHookWithUseEffect(firstRef.current, secondRef.current);

React.useEffect(() => {
console.log("Standard Use effect...");
console.log("firstRef element defined", !!firstRef.current);
console.log("secondRef element ", !!secondRef.current);
}, [firstRef.current, secondRef.current]);

console.log("At RefDemo render", !!firstRef.current , !!secondRef.current);

return (
<div>
<div ref={firstRef}>
My ref is created in the initial render
</div>
<div className="clickme" onClick={() => setVis(true)}>
click me
</div>
{vis && 
<div ref={secondRef}>boo (second ref must surely be valid now?)</div>
}
</div>
)
}

在第一次渲染之后,自定义钩子没有firststref的定义值,但是内联的useEffect有。

单击click-me后,自定义钩子再一次没有获得最近的更新(尽管现在它有了第一个stref值)。

这是预期的吗?

我如何才能实现目标:能够重用地提供使用refs的基于useeffect的代码?

https://jsfiddle.net/GreenAsJade/na1Lstwu/34/


这是控制台日志:

"At RefDemo render", false, false
"CUSTOM Use effect..."
"firstRef element defined", false
"secondRef element", false
"Standard Use effect..."
"firstRef element defined", true
"secondRef element ", false
Now I click the clickme
"At RefDemo render", true, false
"CUSTOM Use effect..."
"firstRef element defined", true
"secondRef element", false
"Standard Use effect..."
"firstRef element defined", true
"secondRef element ", true

问题是您在呈现给自定义钩子时传递了ref.current。现在,当您更改vis的状态时,该组件将再次从上到下执行(读取效果,但尚未执行)。但是在这个渲染中,当你调用自定义钩子时,你的ref还没有更新(因为我们还没有真正的重新渲染,所以把ref赋给了第二个div)。因为你特别传递了ref的值,它不会显示实际更新的ref值,而是你在函数调用时传递的值(null)。当效果随后运行时,您只能访问您传递的显式值,而不像您传递ref本身,其值始终是最新的。这个代码沙箱应该能说明这个问题。

我发现我问了两个问题。这是我找到的答案,"我应该如何实现refs的副作用?">

答案是"不要在useEffect中使用refs"。当然,在某些情况下,它可能是好的,但它肯定是自找麻烦。

相反,使用ref回调来实现创建和销毁ref的副作用。

ref callback的语义更容易理解:在创建节点时调用一个,在销毁节点时调用另一个。

最新更新