如何从我编写的自定义表单 child 组件修改 parent 组件的状态。这也可能影响 parent 的其他 children

How to modify state of a parent component from a child component which is a custom form I wrote. This might also effect other children of the parent

我写了一个名为 SingleFilterContainer

的自定义表单组件

在名为 FiltersContainer 的 parent 组件中,我初始化了一个状态 filters,它最初有一个单一过滤器的数组和相应的 setFilters 函数来修改数组的过滤器。并且还有一个添加过滤器的按钮。在渲染函数中,我使用 filters.map 多次渲染 SingleFilterContainer 组件。到目前为止,这是有效的。但我想添加一个删除过滤器按钮。我把它放在 SingleFilterContainer 里面。当我单击它时,它应该更新 parent 组件中的状态 filters 并删除第 ith 个过滤器并正常呈现其余过滤器。或者重新渲染整个滤镜图。

我是 React 和 Hooks 的新手,我觉得我错过了什么。我这三天都在搞,有点迷路了。

这里是沙盒https://codesandbox.io/s/editing-filters-j2qrp

我觉得我处理状态的方式完全错误。也许我应该使用 redux?但我希望 SingleFilterContainer 像一种短暂的形式。或者删除过滤器按钮应该在 parent 组件内吗?并使用地图重复它?

这是我的 fork

以下是我的修改。

  function handleDeleteFilter(i) {
    setFilters(filters => filters.filter((e, index) => index !== i));
  }

重要提示:

  1. 理想情况下,您需要为数组中的每个项目分配一个 id 属性,而不是按索引进行比较。
  2. 不要直接改变状态。 .splice 直接改变状态。学习使用 .map.filter & .reduce 数组函数

TL;DR Fixed fork

您的代码中的问题是您在渲染 onClick={handleDeleteFilter(i)} 上调用函数 onClick 需要对函数的引用,但是如果您希望此代码起作用,那么您所使用的方法从 parent 传递到 child 也需要 return 一个函数。

那么你的 handleDeleteFilter 将如下所示:

function handleDeleteFilter(i) {
  return function() {
     filters.splice(i, i + 1);
     setFilters(filters => filters);
  }
}

此外,在您的情况下,您不需要将 i + 1 作为第二个参数传递给 splice,因为第二个参数是要删除的项目数量。在你的情况下,这只是 1。Docs

您将 i 传递给第一个函数,第二个函数会因关闭而看到它。

然后是删除一个元素。

改变状态是不好的做法,所以你可以有一个带有状态副本的局部变量,你可以操纵它然后更新状态。这样你就可以使用你想要的任何东西,但是在局部变量上。

所以你更新后的 handleDeleteFilter 看起来像

function handleDeleteFilter(i) {
  return function() {
      const clone = [...filters]
      clone.splice(i, 1);
      setFilters(clone);
  }
}

.filter

function handleDeleteFilter(i) {
  return function() {
      const clone = filters.filter((item, index) => index !== i)
      setFilters(clone);
  }
}

这样您就不需要新变量,因为 .filter return 是一个新数组。 Docs