reactjs - 在渲染期间而不是在 useEffect 中更改 ref 的值是否安全?
问题描述
我useRef
用来保存 prop 的最新值,以便稍后在异步调用的回调(例如 onClick 处理程序)中访问它。我正在使用 ref 而不是放入value
useCallback 依赖项列表,因为我希望该值会经常更改(当此组件使用 new 重新渲染时value
),但 onClick 处理程序将很少被调用,因此不值得分配每次值更改时,都会为元素添加新的事件侦听器。
function MyComponent({ value }) {
const valueRef = useRef(value);
valueRef.current = value; // is this ok?
const onClick = useCallback(() => {
console.log("the latest value is", valueRef.current);
}, []);
...
}
React Strict Mode的文档让我相信在其中执行副作用render()
通常是不安全的。
因为上述方法[包括类组件
render()
和函数组件体]可能会被多次调用,因此它们不包含副作用很重要。忽略此规则会导致各种问题,包括内存泄漏和无效的应用程序状态。
事实上,当我使用 ref 访问旧值时,我在严格模式下遇到了问题。
我的问题是:从渲染函数分配的“副作用”是否有任何顾虑?valueRef.current = value
例如,在任何情况下回调会收到一个陈旧的值(或来自尚未提交的“未来”渲染的值)?
我能想到的一种替代方法是useEffect
确保在组件渲染后更新 ref,但从表面上看,这看起来没有必要。
function MyComponent({ value }) {
const valueRef = useRef(value);
useEffect(() => {
valueRef.current = value; // is this any safer/different?
}, [value]);
const onClick = useCallback(() => {
console.log("the latest value is", valueRef.current);
}, []);
...
}
解决方案
例如,在任何情况下回调会收到一个陈旧的值(或来自尚未提交的“未来”渲染的值)?
括号是主要关注点。
render
当前(和功能组件)调用和实际 DOM 更新之间存在一一对应的关系。(即承诺)
但是很长一段时间以来,React 团队一直在谈论“并发模式”,其中可能会开始更新(render
被调用),但随后会被更高优先级的更新中断。
在这种情况下,如果在取消的渲染中更新了 ref,则 ref 可能最终与渲染组件的实际状态不同步。
这一直是假设性的,但刚刚宣布一些并发模式更改将通过API以一种选择加入的方式登陆 React 18 。startTransition
(也许还有其他一些)
实际上,这在多大程度上是一个实际问题?很难说。 startTransition
是可选的,所以如果你不使用它,你可能是安全的。无论如何,许多参考更新将是相当“安全”的。
但如果可以的话,最好还是谨慎行事。
推荐阅读
- reactjs - 始终使用 React Hooks 获取其他本地状态的初始值
- javascript - 我应该什么时候开始和结束我的 node.js SQL 连接,我应该从一开始就使用池吗?
- java - 当我回到屏幕时游戏停止
- python - win10检测不到conda中pip安装的egg包
- scala - 如何以有效的方式从两个列表中创建一个新列表
- android - 如何通过按钮删除recyclerview适配器中的最后一项?
- python - Python argparse.ArgumentParser 无法区分 `--modes` 和 `--mode`
- django - 为什么我会收到 django 的循环导入错误?
- javascript - 如何显示警告框输出,函数内部也有计算
- algorithm - 如何设计多目标A*star算法?