首页 > 解决方案 > 如何从我编写的自定义表单的子组件修改父组件的状态。这也可能影响父母的其他孩子

问题描述

我写了一个自定义表单组件,叫做SingleFilterContainer

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

我是新来的反应和钩子,我觉得我错过了一些东西。在过去的三天里,我一直在做这件事,我有点迷失了。

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

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

标签: reactjscomponentsreact-hooksstatereact-component

解决方案


TL;DR固定前叉

您的代码中的问题是您在渲染时调用函数需要对函数onClick={handleDeleteFilter(i)}onClick引用,但是如果您希望此代码正常工作,那么您从父级传递给子级的方法也需要返回一个函数。

然后你的handleDeleteFilter会是这样的:

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

同样在您的情况下,您不需要作为第二个参数传入i + 1splice因为第二个参数是要删除的项目数量。在您的情况下,这只是 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返回一个新数组。文档


推荐阅读