Reactjs event.stopPropagation似乎阻止useState更新和渲染
列表中有多行是材质UI扩展面板。这些行是从rowData数组映射的。每行都可以展开。每行还具有一个删除图标,当按下该图标时,应删除该行 第一个问题是,当我单击Delete图标时,行被删除,但单击会传播并打开以下面板Reactjs event.stopPropagation似乎阻止useState更新和渲染,reactjs,state,material-ui,react-hooks,stoppropagation,Reactjs,State,Material Ui,React Hooks,Stoppropagation,列表中有多行是材质UI扩展面板。这些行是从rowData数组映射的。每行都可以展开。每行还具有一个删除图标,当按下该图标时,应删除该行 第一个问题是,当我单击Delete图标时,行被删除,但单击会传播并打开以下面板 <DeleteIcon id={key} onClick={event => { onDelete(event, key); //key is specific row id }} className={classes.icons} />
<DeleteIcon
id={key}
onClick={event => {
onDelete(event, key); //key is specific row id
}}
className={classes.icons}
/>
const onDelete = (event, key) => {
let newCategories = categories;
delete newCategories[key];
setCategories(newCategories);
};
但这不起作用,因为我假设我的单击正在传播,并且我删除的行下的面板正在从onDelete()之后运行的单击事件函数打开
因此,接下来我尝试使用event.stopPropagation:
const onDelete = (event, key) => {
event.stopPropagation();
let newCategories = categories;
delete newCategories[key];
setCategories(newCategories);
};
但是现在该行不会在视图中删除(它在控制台中删除)。我假设event.stopPropagation阻止我的状态(setCategories)强制重新呈现,就像useState钩子中的更改通常所做的那样。但是,如果单击删除图标,则在单击行以展开面板后,状态将更新,行将删除。所以我把event.stopPropagation去掉了,现在我有了这个:
const onDelete = (event, key) => {
let newCategories = categories;
delete newCategories[key];
setCategories(newCategories);
setTimeout(() => {
setExpanded(false);
}, 100);
};
这很有效,并添加了一个整洁的小效果,在删除行之前,下面的面板非常短暂地打开,但我想更好地了解使用event.stopPropagation和使用useState钩子更新状态的情况
编辑:
指向codesandbox的链接:
我将event.stopPropagation()留在onDelete()函数中进行测试。单击“删除”图标,观察任何情况。然后单击该行以展开面板,注意它消失了。谢谢 React正在避免重新渲染,因为您使用完全相同的对象调用了状态设置器。为了保证setter触发重新渲染,您应该创建一个新对象,而不是修改现有对象 更改此项:
const onDelete = (event, key) => {
let newCategories = categories; // this line is the problem
delete newCategories[key];
setCategories(newCategories);
};
改为:
const onDelete = (event, key) => {
// create a new object rather than mutating existing object
let newCategories = { ...categories };
delete newCategories[key];
setCategories(newCategories);
};
请创建一个复制您的问题
event.stopPropagation()
不应对状态更改是否导致重新渲染产生任何影响。添加了上面代码沙盒的链接。谢谢
const onDelete = (event, key) => {
// create a new object rather than mutating existing object
let newCategories = { ...categories };
delete newCategories[key];
setCategories(newCategories);
};