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

event.stopPropagation seems to prevent useState update and render

我在列表中有多行 Material-UI 扩展面板。这些行是从 rowData 数组映射而来的。每行都可以展开。每行还有一个删除图标,当推送时应删除该行。

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

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

首先,我尝试将面板设置为 false 以关闭它:

const [expanded, setExpanded] = useState(false);
...
const onDelete = (event, key) => {
  setExpanded(false)
...

但这不起作用,因为我假设我的点击正在传播,我删除的行下的面板正在从 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 挂钩。

编辑:

Link 到 codesandbox: https://codesandbox.io/embed/61j19k1q13

我在 onDelete() 函数中留下了 event.stopPropagation() 来测试。单击删除图标,看什么也没有发生。然后单击该行以展开面板并注意它消失了。谢谢!

React 正在避免 re-render,因为您使用完全相同的对象调用状态 setter。您应该创建一个新对象而不是改变现有对象,以保证 setter 触发 re-render.

改变这个:

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