Reactjs event.stopPropagation似乎阻止useState更新和渲染

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} />

列表中有多行是材质UI扩展面板。这些行是从rowData数组映射的。每行都可以展开。每行还具有一个删除图标,当按下该图标时,应删除该行

第一个问题是,当我单击Delete图标时,行被删除,但单击会传播并打开以下面板

<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);
};