Reactjs 从对象数组中删除项

Reactjs 从对象数组中删除项,reactjs,Reactjs,我有一个页面显示contatcs信息: contactsInfo.map((info, index) => ( <SearchResultPanel info={info} isAdmin={isAdmin} key={index} handleChange={this.makeHandleChange('se

我有一个页面显示contatcs信息:

contactsInfo.map((info, index) => (
                <SearchResultPanel
                  info={info}
                  isAdmin={isAdmin}
                  key={index}
                  handleChange={this.makeHandleChange('searchResultPanel')}
                />
              )),
以及handleDelete功能:

handleDelete = async contactID => {
    await deleteContact(contactID);
    this.setState(contactInfo:
        this.state.contactInfo.id === contactID? {} : this.state.contactInfo,
    }));
  };
  makeHandleChange = panelName => contactID => {
    this.setState(prevState => ({
      contactsInfo: prevState.contactsInfo.filter(i => i.id !== contactID ),
    }));
  };
如果按升序删除前联系人[2]、联系人[1]、联系人[0]的联系人,一切正常,如果按升序删除前联系人[0]、联系人[1]、联系人[2],第一个联系人被删除,但在console.log中,我看到第二个联系人的状态也被清除,但是第二个联系人仍然显示在页面上,然后当我点击其删除按钮时,什么也没有发生

对于导致这种行为的handleDelete方法,我做错了什么

componentDidUpdate函数:要更新父组件的状态:

  componentDidUpdate(_, prevState) {
    const { handleChange } = this.props;
    if (this.state !== prevState) {
      handleChange(prevState.contactInfo.id);
    }
  }
和父handleChange函数:

handleDelete = async contactID => {
    await deleteContact(contactID);
    this.setState(contactInfo:
        this.state.contactInfo.id === contactID? {} : this.state.contactInfo,
    }));
  };
  makeHandleChange = panelName => contactID => {
    this.setState(prevState => ({
      contactsInfo: prevState.contactsInfo.filter(i => i.id !== contactID ),
    }));
  };
整个父组件:

import React from 'react';

import SearchResultPanel from '../home/SearchResultPanel';

const contactInformation = [
  {
    id: 123,
    routingNumber: 2634545,
    name: 'test',
    date: '01/23/2019',
  },
  {
    id: 1234,
    routingNumber: 2634546,
    name: 'test2',
    date: '01/23/2012',
  {
    id: 1235,
    routingNumber: 2634547,
    name: 'test3',
    date: '01/23/2012',
 },
];


const getContacts = async () => {
  …
};



export default class Home extends React.Component {
  state = {
    contactsInfo: [],
    isAdmin: true,
  };

  handleSubmit = async () => {
    const contactsInfo = await getContacts();
    this.setState({contactsInfo });
  };

  makeHandleChange = panelName => contactID => {
    this.setState(prevState => ({
      contactsInfo: prevState. contactsInfo.filter(i => i.id !== contactID),
    }));
  };

  render() {
    const { contactsInfo, isAdmin } = this.state;
    return (
      <div>
        <div>
          <TextInput
            handleSubmit={this.handleSubmit}
          />

          {{
              contactsInfo.map((info, index) => (
                <SearchResultPanel
                  info={info}
                  isAdmin={isAdmin}
                  key={index}
                  handleChange={this.makeHandleChange('searchResultPanel')}
                />
              )),
        </div>
      </div>
    );
  }
}
import { Component } from 'react';
import InfoItem from '../ui/InfoItem;


const deleteContact = async contactID => {
};

export default class SearchResultPanel extends Component {
  state = {
    contactInfo: {},
  };

  componentDidMount() {
    const { info, handleChange } = this.props;
    this.setState({contactInfo: info });
    handleChange(this.state);
  }

  componentDidUpdate(_, prevState) {
    const { handleChange } = this.props;
    if (this.state !== prevState) {
      handleChange(prevState.contactInfo.id);
    }
  }

  handleDelete = async contactID => {
    await deleteContact(contactID);
    this.setState(prevState => ({
      contactInfo:
        prevState.contactInfo.id === contactID? {} : prevState.contactInfo,
    }));
  };


  render() {
    const { info, isAdmin } = this.props;
    const {
      routingNumber,
      name,
      date,
    } = info;

    return (
      <div>
        <div>
          <div>
            <div>
              <InfoItem header="ROUTING NUMBER" detail={routingNumber} />
              <InfoItem header="NAME" detail={name} />
         <InfoItem header="DATE" detail={date} />
            </div>
          </div>
                <button
                  onClick={() => this.handleDelete(info.id)}
                >
                  <DeleteIcon />
                </button>
              )}
            </div>
          </div>
        </div>
      </div>
    );
  }
}
整个子组件:

import React from 'react';

import SearchResultPanel from '../home/SearchResultPanel';

const contactInformation = [
  {
    id: 123,
    routingNumber: 2634545,
    name: 'test',
    date: '01/23/2019',
  },
  {
    id: 1234,
    routingNumber: 2634546,
    name: 'test2',
    date: '01/23/2012',
  {
    id: 1235,
    routingNumber: 2634547,
    name: 'test3',
    date: '01/23/2012',
 },
];


const getContacts = async () => {
  …
};



export default class Home extends React.Component {
  state = {
    contactsInfo: [],
    isAdmin: true,
  };

  handleSubmit = async () => {
    const contactsInfo = await getContacts();
    this.setState({contactsInfo });
  };

  makeHandleChange = panelName => contactID => {
    this.setState(prevState => ({
      contactsInfo: prevState. contactsInfo.filter(i => i.id !== contactID),
    }));
  };

  render() {
    const { contactsInfo, isAdmin } = this.state;
    return (
      <div>
        <div>
          <TextInput
            handleSubmit={this.handleSubmit}
          />

          {{
              contactsInfo.map((info, index) => (
                <SearchResultPanel
                  info={info}
                  isAdmin={isAdmin}
                  key={index}
                  handleChange={this.makeHandleChange('searchResultPanel')}
                />
              )),
        </div>
      </div>
    );
  }
}
import { Component } from 'react';
import InfoItem from '../ui/InfoItem;


const deleteContact = async contactID => {
};

export default class SearchResultPanel extends Component {
  state = {
    contactInfo: {},
  };

  componentDidMount() {
    const { info, handleChange } = this.props;
    this.setState({contactInfo: info });
    handleChange(this.state);
  }

  componentDidUpdate(_, prevState) {
    const { handleChange } = this.props;
    if (this.state !== prevState) {
      handleChange(prevState.contactInfo.id);
    }
  }

  handleDelete = async contactID => {
    await deleteContact(contactID);
    this.setState(prevState => ({
      contactInfo:
        prevState.contactInfo.id === contactID? {} : prevState.contactInfo,
    }));
  };


  render() {
    const { info, isAdmin } = this.props;
    const {
      routingNumber,
      name,
      date,
    } = info;

    return (
      <div>
        <div>
          <div>
            <div>
              <InfoItem header="ROUTING NUMBER" detail={routingNumber} />
              <InfoItem header="NAME" detail={name} />
         <InfoItem header="DATE" detail={date} />
            </div>
          </div>
                <button
                  onClick={() => this.handleDelete(info.id)}
                >
                  <DeleteIcon />
                </button>
              )}
            </div>
          </div>
        </div>
      </div>
    );
  }
}
您需要更新handleDelete函数。我认为您只是缺少setState函数的开放大括号

handleDelete = async contactID => {
  await deleteContact(contactID);
  this.setState({
    contactInfo: this.state.contactInfo.id === contactID? {} : this.state.contactInfo,
  });
};
键有助于识别哪些项已更改、已添加或已删除 远离的。应该为数组中的元素提供键,以便 这些元素具有稳定的特性

在代码中,使用数组的索引作为键,这是不推荐的

如果项目的顺序可能会改变,我们不建议对键使用索引 改变这可能会对性能产生负面影响,并可能导致问题 具有组件状态。 React将默认使用索引作为键

您应该使用联系人的info.id,因为这样您就可以声明稳定的身份

contactsInfo.map(info => (
                <SearchResultPanel
                  info={info}
                  isAdmin={isAdmin}
                  key={info.id}
                  handleChange={this.makeHandleChange('searchResultPanel')}
                />
              )),

来源:

你能用你的代码创建一个小键盘吗?如果你有联系人信息中的稳定id,你不应该使用数组索引作为键。id@user3378165,向我们显示父组件和子组件的所有代码。看来您管理状态时出错了。@MahediSabuj谢谢,请查看我编辑的问题。@fard谢谢!这就是导致意外行为的原因,我修复了钥匙,解决了问题!你想把它写下来作为答案,这样我就可以接受了吗?