英文:
If the callback of a useEffect contains a state variable not listed in its trigger array, could this create an inconsistency?
问题
const [first, set_first] = useState(false);
const [is_mobile, set_is_mobile] = useState(false);
useEffect(() => {
if (!first) {
window.scrollBy({ top: is_mobile ? -180 : -195 });
}
}, [first]);
is_mobile
不是useEffect
的依赖项,但是它是回调函数的一部分。这可能会导致不一致性吗?
例如,
is_mobile
被更改useEffect
未触发first
被更改。useEffect
会使用is_mobile
的过时值吗?
英文:
const [first, set_first] = useState(false);
const [is_mobile, set_is_mobile] = useState(false);
useEffect(() => {
if (!first) {
window.scrollBy({ top: is_mobile ? -180 : -195 });
}
}, [first]);
is_mobile
is not part of the useEffect
's dependency, but is part of its callback. Could this potentially create an inconsistency?
For example,
is_mobile
is changeduseEffect
is not firedfirst
is changed. WilluseEffect
use the outdated value ofis_mobile
答案1
得分: 2
简短回答:不。
长回答:
React 本身没有魔法,也不修改 JavaScript 语言,它只是使用它。让我们来实际分析一下你的例子:
const [first, set_first] = useState(false);
const [is_mobile, set_is_mobile] = useState(false);
useEffect(() => {
if (!first) {
window.scrollBy({ top: is_mobile ? -180 : -195 });
}
}, [first]);
首先一些通用概念:
-
useState
将返回当前值(初始化为给定的initialValue
,如果没有提供则为undefined
),这是一个常量,以及一个设置器函数。 -
useEffect
将接受回调函数,并且只有在给定的依赖数组与上一次执行时的依赖数组 "浅层不同" 时才执行它(并且第一次始终调用)。 -
因为你的组件在一个函数中定义,所以唯一的渲染方法是调用它。
现在,假设你想修改一个状态,你调用它的设置函数:
set_is_mobile(true);
这个函数是由 React 提供的,所以我们不知道确切发生了什么,但我们可以想象:
- React 在某个内部数组或对象中存储新值。
- 它再次调用组件函数:这是一次 "重新渲染"。
在这个新的渲染中,相同的 useState()
指令再次被调用(这就是为什么它们始终以相同的顺序被调用非常重要),但它返回新的值和相同的设置函数。其他状态没有改变,因此它们的值保持不变。
useEffect
也被调用,但依赖数组相同(first
值没有改变),因此回调被忽略。但是回调已经具有更新后的 is_mobile
值,如果它被调用的话。
现在,你决定更新第二个状态,set_first(true)
。再次触发重新渲染,发生完全相同的过程。新的更新后的 first
状态由第一个 useState
返回,而 "不是新的但仍然更新后的" is_mobile
状态由第二个 useState
返回。然后,useEffect
也被调用,并且传递给它的回调函数具有两个更新后的值,与以往一样。但是这次,因为 first
的值已更改,React 调用了回调。并且它有所有更新后的值。
总结:
useEffect
的依赖项控制回调函数何时被调用,但在其中使用的每个值始终是最新的。
希望这些解释清楚并满足你对 React 状态和效果的理解!
英文:
Short answer: no.
Long answer:
React by it-self contains not magic and does not modify the JS language, it only uses it. Let's be practical and take your example:
const [first, set_first] = useState(false);
const [is_mobile, set_is_mobile] = useState(false);
useEffect(() => {
if (!first) {
window.scrollBy({ top: is_mobile ? -180 : -195 });
}
}, [first]);
Some generic concept first:
-
useState
will return the current value (initialized to the giveninitialValue
orundefined
if no one is present), which is a constant btw, and a setter function. -
useEffect
will take the callback and execute it if the dependency array given is "shallow different" than on the previous execution (and the first time it is always called). -
Because your component is defined in a single function, the only way it could render it is to call it.
OK, now that we have made clear the basic concepts, let's consider you want to modify a state. You call its setter function:
set_is_mobile(true);
This function is provided by React, so we don't know exactly what happens, but we can imagine:
- React store the new value is some internal array or object.
- It calls the component function once again: It's a "re-render".
On this new render, the same exact useState()
instruction is invoked (this is why it's so important for them to always be invoked in the same order), but it returns the new value, and the same setter function. The other states did not changed, so the same value is returned for them.
The useEffect
is called too, but the dependency array is the same (first
value did not changed) so the callback is ignored. However, the callback had the updated value for is_mobile
, if it were invoked.
Now you decide to update the second state, set_first(true)
. Once again, a re-render is triggered, and the same exact process occurs. The newly up-to-date first
state is returned by the first useState
, and the "not-new-but-still-up-to-date" is_mobile
state is returned by the second useState
. Then, the useEffect
is called, and the callback passed to it has the two up-to-date values, as always. But this time, because the value of first
changed, the callback is being invoked by React. And it has all the up-to-date values.
To sum-up:
The dependencies of the useEffect
controls when a callback is being invoked, but every values used inside are always up-to-date.
I hope this was clear and satisfies your comprehension about React states and effects!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论