我目前正在学习react,无意中发现了他们的“教程”部分中的一个部分,名为“描述UI”。我无法理解一个名为“保持组件纯净”的小节。我不明白的是:
给定以下代码:
let guest = 0;
function Cup() {
// Bad: changing a preexisting variable!
guest = guest + 1;
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}
为什么输出看起来像这样:客人茶杯#2客人茶杯#4客人茶杯#6
而不是像这样客人用茶杯#1客人用茶杯#2客人用茶杯#3
我想自己弄明白,但我做不到。
2条答案
按热度按时间ebdffaop1#
这可能是因为,在开发模式下,React会在挂载时渲染所有内容两次。你可以通过在
Cup
中添加以下内容来证明这一点:即使
useEffect
没有依赖项并且应该只运行一次,您也会看到每个Cup
打印两次“cup”。考虑到这一点,每个
Cup
组件被渲染两次。您有三个,因此最终渲染显示每个组件第二次渲染后的结果,设置为2,4和6。然而,像这样将状态保存在全局变量中并不是正确的做法,并且会导致意外的行为。正如您提到的,
Cup
应该是一个“纯”组件,它对全局变量guest
的依赖性是违反直觉的。一个更好的方法是告诉
Cup
接受一些输入,并始终显示该输入。这被称为props
(properties
的缩写),并允许您纯粹基于状态渲染cup,这在其他地方进行管理。一个服务建议:这样就可以在
TesSet
中保存一个guest的状态,然后循环遍历它。一个更高级的例子:这允许您从
TeaSet
中操作状态,而不会影响现有客户机的单个cup,也不依赖于任何全局变量,而全局变量可能会以意外的方式进行处理。ruarlubt2#
在开发模式下,React渲染你的组件两次,这对调试很有用(更容易找到不需要的行为,最明显的用例可能是
useEffect()
)。我怀疑你的index.js中有一个
<React.StrictMode/>
元素,这是导致这种行为的组件,但我建议不要删除它。如果渲染是一个步骤,那么所有的计算都必须与步骤相关,我绝对建议不要在你的组件中使用外部变量,正确的方法是让另一个组件负责渲染
<Cup/>
并将值作为prop传递。