-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useLatest是否属于渲染期间修改? #2495
Comments
合理,理论上可以增加一个变化检测再给 ref.current 赋值。 function useLatest(value) {
const ref = useRef(null);
if(value !== ref.curent) {
ref.current = value;
}
return ref;
} 这样可能更好一点。避免了每次渲染都赋值。 |
交给我吧,感谢~ |
关于 React 官方文档里声明的 原本一直以为一刀切的方式,绝对遵循这个原则就好了,但是业务逻辑中有很多不好绕过的闭包问题,需要 ref 穿透一下,这样做并发模式下可能存在问题,但也立竿见影地把闭包问题解决了,所以有时我们还离不开渲染阶段读写 ref 的操作。 为了拥抱 React 未来,拥抱并发模式,我们要遵循这个原则,但也不是要一刀切的方式去遵循,比如,官方自己也举例了初始赋值时可以在渲染阶段读写 ref:https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents, 说明只要行为可控,是可以打破上述原则的。 首先,渲染阶段读写 ref 并直接参与 DOM 渲染是不允许的,因为函数不再是纯的: 其次,在“副作用”(side effects, 所以我认为,在渲染阶段“写 ref”来保存一个变量的最新引用,并在“副作用”中“读 ref”来穿透闭包,并没有导致不可控,也不会导致函数不纯,只要危险操作被收敛到了“副作用”区域,就是合法的。 回到 const [count] = useState(0);
// 渲染阶段“写 ref”了(useLatest 内部会写 ref)
const countRef = useLatest(count);
// 然后,又在渲染阶段“读 ref” 了
return <div>{countRef.current}</div>; 这个例子在渲染阶段既写 ref,又读 ref,危险操作被收敛到 DOM 上,导致函数不纯,这样肯定是不行的。 总之, 转 ahooks 作者大龙哥的建议:useLatest 存函数输入,useMemoizedFn 存函数输出。这样用没什么问题~ 如果真有问题的话,那就水多了加面,面多了加水,没法一棒子打死。 |
个人感觉目前 useLatest 的源码不太需要修改,主要是文档需要说明:useLatest 的返回值应该只用于在“副作用”区域解决闭包问题,不能直接用于 DOM 渲染。 |
额嗯 ,问题不大。这个可以先不改 |
@liuyib 大佬请问一个问题
https://react.docschina.org/reference/react/useRef#avoiding-recreating-the-ref-contents
通常情况下,在渲染过程中写入或读取 ref.current 是不允许的
允许做法
The text was updated successfully, but these errors were encountered: