Reputation: 3255
In a React app I have a component that lists people invited to a project. When I remove an item from the array that's used as the source for the list, React isn't updating the list on the page.
The list of invites are passed to the component as props
. There is a link on each invite to cancel the invitation, to this event I have attached a function that removes that invite from the array, but for some reason it is not being removed from the list shown on the page.
This list of invites is created inside the component via a function I've created;
function invites(teamInvites) {
if (!teamInvites) {
return null;
}
return (
<ul className={styles.pendingInvites}>
{teamInvites.map((invite, index) => (
<li key={invite.id} id={invite.id}>
<span class={styles.email}>{invite.email}
<span className={styles.pending}>Pending</span></span>
<span class={styles.right}>
<a onClick={() => {actionResendTeamUserInvite(teamId, teamName, invite.email)}}>Resend Invite</a> |
<a onClick={() => {removeInvite(invite.email)}}>Cancel</a>
</span>
</li>
))}
</ul>
);
}
This is called in the component like this;
{invites(teamInvites)}I then have a function which removes the invite from the teamInvites
array;
const removeInvite = (email) => {
actionRemoveTeamUserInvite(teamId, email);
let index = 0;
let removeAtIndex = -1;
teamInvites.forEach(invite => {
if (invite.email === email) {
removeAtIndex = index;
}
index++;
});
if (removeAtIndex >= 0) {
removeAtIndex = -1;
}
return false;
}
I have confirmed that the array itself is being updated by outputting the length of the array, which reduces by one each time the function above is executed.
Why does the view itself not update along with the array?
Upvotes: 0
Views: 73
Reputation: 370679
Put the teamInvites
prop into state, and then when removeInvite
is called, you can use the index of the mapped invite to remove it from the state array:
const Invites = ({ teamInvites }) => {
if (!teamInvites) {
return null;
}
const [teamInvitesState, setTeamInvitesState] = useState(teamInvites);
const removeInvite = (i) => {
setTeamInvitesState([
...teamInvitesState.slice(0, i),
...teamInvitesState.slice(i + 1)
]);
};
return (
<ul className={styles.pendingInvites}>
{teamInvites.map((invite, index) => (
<li key={invite.id} id={invite.id}>
<span class={styles.email}>{invite.email}
<span className={styles.pending}>Pending</span></span>
<span class={styles.right}>
<a onClick={() => {actionResendTeamUserInvite(teamId, teamName, invite.email)}}>Resend Invite</a> |
<a onClick={() => {removeInvite(index)}}>Cancel</a>
</span>
</li>
))}
</ul>
);
};
And call it like:
<Invites {...{teamInvites}} />
Upvotes: 1
Reputation: 502
You need to set the state to the modified array. Only then will the re rendering and the mapping of updated array array will take place
Upvotes: 0
Reputation: 1723
You need to pass the invites array of values again to rerender the component.
This is what Redux would do if the update is done with an action and the change of global state rerenders the component because it's passed as property when you connect the state with the component.
Or, once you get the invites array of values as a property set it on an internal state and update the state on the removeInvite function.
Upvotes: 0