user3378165
user3378165

Reputation: 6926

Remove item from objects array

I have a page that renders contatcs informatios:

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

The contactsInfo is an array of contactInfo objects.

On the SearchResultPanel component I have an option to delete the current contact:

<button onClick={() => this.handleDelete(info.id)}>

and the handleDelete function:

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

If I delete the contacts in a descending order for ex contacts[2], contacts[1], contacts[0] everything works fine, if I delete the contacts in an ascending order for ex contacts[0], contacts[1], contacts[2], the first contact gets deleted but in a console.log I see that the state of the second contact is also being cleared however the second contact still shows on the page, then when I hit its delete button nothing happens...

What am I doing wrong ont the handleDelete method that causes such a behavior?

componentDidUpdate function: To update the parent component's state:

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

and the parent handleChange function:

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

Entire parent component:

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

Entire child component:

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

Upvotes: 0

Views: 111

Answers (2)

r g
r g

Reputation: 3901

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

In your code you are using index of array as a key, which is not recommended.

We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. React will default to using indexes as keys.

You should use your info.id from contact, because then you declare stable identity

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

source: https://reactjs.org/docs/lists-and-keys.html

Upvotes: 1

Hitesh Chaudhari
Hitesh Chaudhari

Reputation: 715

You need to update the handleDelete function. I think you are just missing the open curly brace of setState function.

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

Upvotes: 0

Related Questions