Reputation: 6926
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
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
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