我有一个context/provider,它有一个WebSocket作为状态变量。一旦socket被初始化,onMessage回调就被设置。回调如下所示:
const wsOnMessage = (message: any) => {
const data = JSON.parse(message.data);
setProgress(merge(progress, data.progress));
};
在组件中,我有这样的内容:
function PVCListTableRow(props: any) {
const { pvc } = props;
const { progress } = useMyContext();
useEffect(() => {
console.log('Progress', progress[pvc.metadata.uid])
}, [progress[pvc.metadata.uid]])
return (
{/* stuff */}
);
}
但是,当progress
变量更新时,效果不会触发。progress
变量的数据结构如下所示
{
"uid-here": 0.25,
"another-uid-here": 0.72,
...etc,
}
当与pvc.metadata.uid
匹配的属性更新时,如何触发useEffect?
或者,当该值被更新时,我如何让组件重新呈现?
4条答案
按热度按时间djmepvbi1#
引用文件:
传递给
useEffect
的函数将在渲染提交到屏幕后运行。这是关键部分(许多人似乎忽略了):使用提供给
useEffect
的依赖性列表来 * 限制 * 其调用,但不设置"提交呈现之后“之外的某些条件。换句话说,如果React认为您的组件没有更新,那么
useEffect
钩子就不会被调用!现在,从您的问题中还不清楚您的上下文(
progress
)到底是什么样子的,但是这一行:......非常可疑。
请参见,要让React跟踪 object 中的更改,该对象的引用应该更改。现在,
setProgress
很可能只是将值(作为参数传递)赋给变量,而不执行任何克隆,无论是浅克隆还是深克隆。然而,如果代码中的
merge
与lodash.merge
相似(同样,很有可能它实际上是lodash.merge; JS生态系统现在不是很大),它不会返回一个新对象;而是将值从data.progress
重新分配到progress
,并且返回后者。很容易检查:将上述一行改为.
现在,在本例中将创建一个新对象,并将其值传递给
setProgress
。当然,你可以在那里做一些检查,看看你是否真的应该强制值更新,但是即使没有这些检查,它也应该有足够的性能。ecfsfe2w2#
似乎没有问题...你确定
pvc.metadata.uid
键在progress对象中吗?slhcrj9b3#
Spread操作符创建一个新的引用,因此它将触发渲染
如果只使用下面的代码段,则不会重新呈现
egdjgwm84#
尝试
[progress['pvc.metadata.uid']]