Reputation: 150
Could you help me with this please guys?
I'm mapping this emails
state but when I remove an email from the array in handleDelete
the map
doesn't re-render. When I console.log(emails)
it's right, the email is removed correctly.
import { TextField, Chip, Avatar } from "@material-ui/core";
import React, { useState } from "react";
import "./Email.css";
export default function Email() {
const [value, setValue] = useState<string>();
const [emails, setEmails] = useState<string[]>([]);
function onTextChange(e: any) {
setValue(e.target.value.replace(" ", ""));
if (value?.includes(",")) {
let separated = e.target.value.split(",");
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const newEmails = separated.filter((val: any) => re.test(val));
if (newEmails[0] !== undefined) {
emails.push(newEmails[0]);
setEmails(emails);
console.log(emails);
}
setValue("");
}
}
function handleDelete(email: string) {
const index = emails.indexOf(email);
if (index > -1) {
setEmails(emails.splice(index, 1));
console.log(email, "removed");
console.log('new list', emails)
}
}
return (
<div>
<TextField
value={value || ""}
variant='outlined'
onChange={onTextChange}
id='textInput'
InputProps={{
startAdornment: (
<div style={{ top: "50%" }}>
{emails.map((email: any) => (
<Chip
label={email}
key={email}
avatar={<Avatar>{email[0].toUpperCase()}</Avatar>}
onDelete={() => handleDelete(email)}
style={{ display: "-webkit-inline-box" }}
/>
))}
</div>
),
}}
/>
</div>
);
}
Upvotes: 3
Views: 2756
Reputation:
Yes, I have met a similar problem before. First, it's because the "emails" variable is not changed. So I mean you call emails.splice function but the email variable not changed. You should create new array variable and set the changed value into it. Only that React state change listener can understand "emails" value changed so "I should render function again..".
function handleDelete(email: string) {
const newEmails = [...emails];
const index = newEmails.indexOf(email);
if (index > -1) {
setEmails(newEmails.splice(index, 1));
}
}
Upvotes: 0
Reputation: 765
The issue is this line setEmails(emails.splice(index, 1));
Splice just changes the array in place so the memory location doesn't change for the array, so react doesnt see a change.
You want something like this
setEmail(prevEmails => prevEmails.filter(e => e !== email))
Upvotes: 5