我目前正在使用React组件,我在Area component
中遇到了共享状态的问题。组件有一个count state
,当创建组件的多个示例时就会出现问题。
function Area({ title }) {
const [count, setCount] = useState(0);
return (
<div>
<h2>current area : {title}</h2>
<div>
<button type="button" onClick={() => setCount(count + 1)}>
+1
</button>
<div>count : {count}</div>
</div>
</div>
);
}
const menuInfos = [
{ title: "aaaaaa", children: <Area title="aaaaaa" /> },
{ title: "bbbbbb", children: <Area title="bbbbbb" /> },
{ title: "cccccc", children: <Area title="cccccc" /> },
{ title: "dddddd", children: <Area title="dddddd" /> },
{ title: "eeeeee", children: <Area title="eeeeee" /> }
];
在当前代码中,Area component
在Menu component
中使用,并为每个菜单项创建一个示例。但是,当Area component
跨多个菜单项使用时,count变量是共享的,这会导致意外的行为。
代码沙箱工作链接:https://codesandbox.io/s/goofy-wind-59v5j9?file=/src/_app.js
我想了解这项工作的原因,并找到一个解决方案,以管理计数状态的每一个菜单项。我将感谢任何关于如何修改代码以实现这一目标的建议。
我已经利用Area component
中的useEffect hook
使用console.log记录卸载阶段,卸载过程似乎运行正常。 此外,我使用www.example.com比较了
menuInfos array的子组件(作为
props传递到
Menu component`Object.is,它们被识别为不同的对象。
然而,尽管有这些观察,我仍然很难完全理解手头的问题。看来我可能忽略了一些关键的东西在我的理解。
5条答案
按热度按时间blmhpbnm1#
您应该使用数组来存储将填充组件的数据,而不是在数组中设置子组件。使用一个小的CSS技巧,即使你在组件之间循环,你也可以保留你的数据:
此外,here是一个可用的codesandbox示例
wtlkbnrh2#
React在渲染过程中使用了一个名为
key
的属性,所以它不会更新不需要更新的东西。如果一个父对象的子对象的key
和以前的一样,那么它将进行优化的、简化的渲染,这显然意味着{count}
的更新不会被完成。这是一个不同的组件,但React不知道它。添加
key
属性将使您的代码工作:**更新:**代码“工作”,但可能不是你想要的...因为一次只渲染一个组件,所以其他组件似乎被卸载并丢失了它们的状态。下次再次显示组件时,将再次创建其状态,并再次从0开始。
tyg4sfes3#
我会对你完全诚实:我不能完全解释,为什么你的解决方案不起作用。我最好的猜测是,你的“孩子”并不是真正独立的
Area
示例,而是同一个示例,只是标题不同。我重写了你的元素Map,使它按预期工作。请尝试一下:
正如您所看到的,我复制了menuInfo的Map,创建了真正独立的
Area
示例,并使用条件语句只显示正确的Area
。计数状态现在彼此分离。o4hqfura4#
您在
Area
组件中遇到的共享状态问题是因为useState
钩子创建了特定于该组件的每个示例的本地状态。在当前代码中,menuInfos
数组创建了Area
组件的多个示例,但它们都共享相同的count
状态。您需要将key
传递给Area
的每个组件以唯一地标识它。您的更新代码:
此外,如果你还想保留Area的每个组件的状态,你需要像这样更新你的代码:
状态在组件之间隔离。React根据组件在UI树中的位置跟踪哪个状态属于哪个组件。可以控制何时保留状态以及何时在重新渲染之间重置状态。
UI树浏览器使用许多树结构来建模UI。DOM表示HTML元素,CSSOM对CSS做同样的事情。甚至还有一个可访问性树!
React还使用树结构来管理和建模您创建的UI。React从你的JSX创建UI树。然后React DOM更新浏览器DOM元素以匹配UI树。在这种情况下,UI树也能够保留每个
Area
组件的状态,因为它们在UI树中的位置是唯一的。有用资源:https://dev.to/muneebkhan4/how-react-preserve-and-reset-state-38la
72qzrwbm5#
解决方案是确保所有子元素具有不同的位置。
这一更改将使您的代码工作:
为什么?因为返回一个数组,例如。
[false, false, <Area />]
,可见区域元素位于第三个位置。React使用类型和位置来确定哪个元素使用哪个状态。但是,当您在Area元素之间切换时,它们将被卸载,每次都重置它们的状态。
你可以通过将它们都放在DOM中并在视觉上隐藏它们来解决这个问题: