useCallback vs useRef misguidance (confounding useRef with object ref)
还没有人认领这个 Issue。
- 主要语言
- JavaScript
- 星标
- 11.8k
- 派生
- 7.9k
- 平均合并
- 1 天 11 小时
- 30 天内合并 PR
- 11
描述
The Proposal
As part of a deductive exercise, in this issue I essentially proposed changing:
x = useCallback(cb , []);
To:
x = useRef(cb).current;
With useRef:
- No deps comparison (
Object.is). - No reallocation of empty array on each render.
These optimisations are terribly minute, but understanding React is what at stake here.
The Question
Then the reply came:
Is there ever a situation where a dependency-less useMemo or useCallback would be a better choice than useRef?
The Docs
I couldn't think of one, so posted an SO question, for which a reply came with reference to these docs:
We didn't choose useRef in this example because an object ref doesn't notify us about changes to the current ref value. Using a callback ref ensures that even if a child component displays the measured node later (e.g. in response to a click), we still get notified about it in the parent component and can update the measurements.
In the codesandbox example provided, we see useCallback with empty dependencies:
const measureRef = useCallback(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}
}, []);
Yet changing the useCallback above to useRef(cb).current works all the same:
const measureRef = useRef(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}
}).current;
Misguidance?
Now I understand the docs focus on a callback ref, so using useCallback makes sense.
But this statement is misleading:
We didn't choose
useRefin this example because an object ref...
First, it promotes the (in my view somewhat popular) misconception that useRef is solely there to refer to DOM elements (filled via object ref).
Further, this statement confounds useRef with object ref:
- object ref vs callback ref is one thing
useRefis another.
What useRef is Really for
Far from this, useRef raison d'être is the ability to create stable values; callbacks are no exception:
const stableCallback = useRef(()=> { ... }).current;
Storing DOM elements is a popular, yet a specific use case for refs.
Another Example
From the docs:
Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.
I argue that this statement distorts people's understanding of core React concept. It builds a mental model where there is such 'cosmic' mapping:
useRef→ object refuseCallback→ callback ref
This is incorrect.
(Nitpickers, like me, will point out at this point that both "object ref" and "callback ref" have "ref" in them!)
What needs changing?
First, useRef should not be part of this sentence:
We didn't choose
useRefin this example because an object ref...
Instead:
We didn't use an object ref as it doesn't notify...
Also this:
Keep in mind that useRef doesn’t notify you when its content changes...
To this:
Keep in mind that object refs don't notify you when its content changes...
Then, if useRef(cb).current is identical to (and slightly more efficient than) useCallback(cb, []), perhaps this is something worth mentioning?
More generally, if correct, I would expect to see this somewhere in the docs:
useMemo(x, [])anduseCallback(cb, [])are the identical touseRef(x).currentanduseRef(cb).currentrespectively.
Learning this is conceptually important, thus so is teaching.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从所引用的 hooks-faq.md 和 hooks-reference.md 部分开始,并结合 issue 提议的措辞检查 callback-ref 示例。在决定应更改哪些术语或说明之前,先验证关于对象 ref、useRef、useMemo 和 useCallback 的说法是否准确;完成的标准是文档在技术上准确,并且区别清晰。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- javascript, react
- 领域
- documentation
- Issue 类型
- 文档
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100