(React) 从数组中移除元素

(React) Remove Element from an Array

希望你一切都好。我环顾四周已经有一段时间了,一直找不到解决我遇到的这个问题的方法。我遇到的问题是我无法从显示的数组中删除项目。我无法删除它的原因是,一旦该元素显示在子组件中,然后再带回父组件,它就不再具有与原来相同的 shape当它进入子组件时。它作为一个数组进入子组件,并且作为一个对象从它出来,具有额外的复杂层。谁能帮我理解为什么那个对象(凝视的)会改变它的形状,以及我如何将它的形状保存为一个数组,然后从中删除元素?

当它returns到父组件时,我无法将数组保存为数组。

我查看了许多资源,但无法弄清楚。我正在尝试从数组中删除一个对象,以便实时将其从 React 中删除。问题是,当 prevState.mapped(object) 从渲染数组中渲染每个对象的各个卡片的组件返回时,它没有被识别为数组。我相信这与 formik 有关。我尝试了以下方法:

我环顾四周,但我一定没有问正确的问题,因为我没有得到关于为什么我正在使用的 prevState 对象一旦出现就不是数组的答案回到父组件。我不怀疑这个问题的解决方案相当简单。我粘贴了以下相关代码:它是按 运行:

的顺序粘贴的

1.) 这部分代码进行 AXIOS 调用,当调用成功时,该数据将被过滤到卡片组件中。

class Organizations extends Component {
  constructor(props) {
    super(props);
    this.state = { organizations: [], mappedOrgs: [] };
  }

  //ORG LOAD
  componentDidMount() {
    paginatedList(0, 8).then(this.onOrgSuccess);
  }

  //ORG CALL SUCCESS

  onOrgSuccess = (config) => {
    let organizations = config.item.pagedItems;
    this.setState((prevState) => {
      return {
        ...prevState,
        mappedOrgs: organizations.map(this.mapOrg),
      };
    }, this.stateChanged);
  };

  mapOrg = (Organization) => (
    _logger(Organization, "ORGANIZATION, ORGANIZATION"),
    (
      <OrgCard
        Organization={Organization}
        key={Organization.id}
        editOrganization={this.editOrganization}
        deleteFunction={this.deleteFunction}
      />
    )
  );

2.) 下面是卡片组件中的函数。 'Handle Delete' 函数也确实通过组件,因此,我也描绘了它。明明是整体渲染的组件的一部分

const OrgCard = ({ Organization, editOrganization, deleteFunction }) => {
  //OPERATIONAL FUNCTIONS
  _logger(Organization);

  //DELETE
  const OrgDelete = () => {
    deleteOrg(Organization.id).then(deleteSuccess).catch(deleteToastFail);
  };

  //SUCCESS FUNCTIONS

  const deleteSuccess = () => {
    deleteFunction(Organization);
  };

    <Button
      onClick={OrgDelete}
      className="btn-danger btn-lg center"
      align="center"
    >
      Delete
    </Button>

下面是应该从数组中删除的函数。这是您在上面看到的组件的父组件,并且与编号为“1”的代码体位于同一代码体中。违规代码周围有两颗星,实际代码中显然没有两颗星。

  deleteFunction = (deletedOrg) => {
    this.setState((prevState) => {
      const indexOfOrg = **prevState.mappedOrgs**.findIndex(
        (Org) => Org.id === deletedOrg.id
      );
      let updatedOrgs = [...prevState.mappedOrgs];
      if (indexOfOrg >= 0) {
        updatedOrgs.slice(indexOfOrg, 1);
      }
      _logger(updatedOrgs);

      return { mappedOrgs: updatedOrgs };
    }, this.stateChanged);
  };

我不了解 Formik,道具验证非常好,所以我将 post 下面的内容也与它相关。

这是编号为'1'的代码体内的道具验证

Organizations.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func,
  }),
  findIndex: PropTypes.func,
  deleteFunction: PropTypes.checkPropTypes({
    deletedOrg: PropTypes.number,
    mappedOrgs: PropTypes.array,
    findIndex: PropTypes.func,
    updatedOrgs: PropTypes.array,
    splice: PropTypes.func,
    indexOfOrg: PropTypes.number,
  }),
};

我已经尝试了很多东西,我什至在卡片渲染中也进行了道具验证。在这种情况下,这是在“2”中。

OrgCard.propTypes = {
  Organization: PropTypes.shape({
    id: PropTypes.number,
    OrganizationTypeId: PropTypes.number,
    name: PropTypes.string,
    description: PropTypes.string,
    logo: PropTypes.string,
    locationId: PropTypes.number,
    phone: PropTypes.string,
    siteUrl: PropTypes.string,
  }).isRequired,
  deleteOrg: PropTypes.func,
  deleteFunction: PropTypes.func,
  editOrganization: PropTypes.func,
};

这是第一段代码。

class Organizations extends Component {
  constructor(props) {
    super(props);
    this.state = { organizations: [], mappedOrgs: [] };
  }

  //ORG LOAD
  componentDidMount() {
    paginatedList(0, 8).then(this.onOrgSuccess);
  }

  //ORG CALL SUCCESS

  onOrgSuccess = (config) => {
    let organizations = config.item.pagedItems;
    this.setState((prevState) => {
      return {
        ...prevState,
        mappedOrgs: organizations.map(this.mapOrg),
      };
    }, this.stateChanged);
  };

  mapOrg = (Organization) => (
    _logger(Organization, "ORGANIZATION, ORGANIZATION"),
    (
      <OrgCard
        Organization={Organization}
        key={Organization.id}
        editOrganization={this.editOrganization}
        deleteFunction={this.deleteFunction}
      />
    )
  );

  //DELETE

  deleteFunction = (deletedOrg) => {
    this.setState((prevState) => {
      const indexOfOrg = prevState.mappedOrgs.findIndex(
        (Org) => Org.id === deletedOrg.id
      );
      let updatedOrgs = [...prevState.mappedOrgs];
      if (indexOfOrg >= 0) {
        updatedOrgs.slice(indexOfOrg, 1);
      }
      _logger(updatedOrgs);

      return { mappedOrgs: updatedOrgs };
    }, this.stateChanged);
  };

  //MAP ORG


  editOrganization = (Organization) => {
    this.props.history.push(
      `/organization/${Organization.id}/edit`,
      Organization
    );
  };
  //RENDER
  render() {
    return (
      <div className="col-12">
        <div className="row">{this.state.mappedOrgs}</div>
      </div>
    );
  }
}

Organizations.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func,
  }),
  findIndex: PropTypes.func,
  deleteFunction: PropTypes.checkPropTypes({
    deletedOrg: PropTypes.number,
    mappedOrgs: PropTypes.array,
    findIndex: PropTypes.func,
    updatedOrgs: PropTypes.array,
    splice: PropTypes.func,
    indexOfOrg: PropTypes.number,
  }),
};

export default Organizations;

这是第二段代码。

const OrgCard = ({ Organization, editOrganization, deleteFunction }) => {
  //OPERATIONAL FUNCTIONS
  _logger(Organization);

  //DELETE
  const OrgDelete = () => {
    deleteOrg(Organization.id).then(deleteSuccess).catch(deleteToastFail);
  };

  //SUCCESS FUNCTIONS

  const deleteSuccess = () => {
    deleteFunction(Organization);
  };

  //FAIL FUNCTION

  const deleteToastFail = () => {
    toast.error("Delete Error", {
      closeOnClick: true,
      position: "top-center",
    });
  };

  //EDIT

  const handleEdit = () => {
    editOrganization(Organization);
  };

  return (
    <Card className="col-lg-6 col-md-6 col-sm-6">
      {" "}
      <CardHeader style={{ fontWeight: "bold" }} className="text-center">
        {Organization.name}
      </CardHeader>
      <CardBody>
        <CardImg src={Organization.logo} />
        {/* <CardText>
          <span>{Organization.description.slice(0, 120)}</span>
        </CardText> */}
        <CardText>
          <span>{Organization.id}</span>
        </CardText>
        <Button
          onClick={handleEdit}
          className="btn-sucess btn-lg center"
          align="center"
        >
          Edit
        </Button>
        <Button
          onClick={OrgDelete}
          className="btn-danger btn-lg center"
          align="center"
        >
          Delete
        </Button>
      </CardBody>
    </Card>
  );
};

OrgCard.propTypes = {
  Organization: PropTypes.shape({
    id: PropTypes.number,
    OrganizationTypeId: PropTypes.number,
    name: PropTypes.string,
    description: PropTypes.string,
    logo: PropTypes.string,
    locationId: PropTypes.number,
    phone: PropTypes.string,
    siteUrl: PropTypes.string,
  }).isRequired,
  deleteOrg: PropTypes.func,
  deleteFunction: PropTypes.func,
  editOrganization: PropTypes.func,
};

export default OrgCard;

你能解释一下为什么要将数组从 child 传回 parent 吗?

我认为正确的结构是 parent 将数组存储在其状态中。然后它可以将数组传递给 child。它还应将删除函数传递给 child(此函数应将索引作为参数)。此函数定义在 parent 中。 parent 通过传递函数名将函数传递给 child。 child,如果它想从数组中删除一个项目,将调用该函数并将要删除的项目的索引传递给它。该函数(位于 parent 中)然后将从其数组(存储在 parent 的状态中)中删除该项目。这会自动导致 child 中显示的数组也更新。

这个想法是数组应该只从 parent 传递到 child。 parent 应该处理所有数组操作。 child 应该只通过调用函数(从 parent 传递给它的函数)将信息 关于 数组传递给 parent相关参数,例如索引。

以下是我针对这个问题得出的解决方案。希望对其他人有帮助。

  removeFromArray = (deletedCompany) => {
this.setState((prevState) => {
  const indexOfCompany = prevState.Companies.findIndex(
    (removeCompany) => removeCompany.id === deletedCompany.id
  );
  if (indexOfCompany === -1) {
    this.toastErrorDelete();
    return;
  } else {
    const updatedCompanies = [...prevState.Companies];
    updatedCompanies.splice(indexOfCompany, 1);
    return { Companies: updatedCompanies };
  }
}, this.clearForm());

};