Карта React не отображается повторно при изменении состояния

#javascript #reactjs

#javascript #reactjs

Вопрос:

Не могли бы вы помочь мне с этим, пожалуйста, ребята? Я отображаю это emails состояние, но когда я удаляю электронное письмо из массива в handleDelete map , оно не отображается повторно. Когда я console.log(emails) все правильно, электронное письмо удаляется правильно.

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

Ответ №1:

Проблема в том, что это setEmails(emails.splice(index, 1)); соединение строк просто изменяет массив на месте, поэтому расположение памяти для массива не меняется, поэтому react не видит изменений.

Вы хотите что-то вроде этого setEmail(prevEmails => prevEmails.filter(e => e !== email))

Комментарии:

1. Большое вам спасибо! Решена проблема, и это намного понятнее, чем мое решение!

Ответ №2:

Да, я уже сталкивался с подобной проблемой раньше. Во-первых, это потому, что переменная «электронные письма» не изменяется. Итак, я имею в виду, что вы вызываете функцию email.splice, но переменная email не изменилась. Вы должны создать новую переменную массива и установить в нее измененное значение. Только тот слушатель, который реагирует на изменение состояния, может понять, что значение «электронные письма» изменилось, поэтому «я должен снова отобразить функцию ..».

 function handleDelete(email: string) {
  const newEmails = [...emails];
  const index = newEmails.indexOf(email);
  if (index > -1) {
     setEmails(newEmails.splice(index, 1));
  }
  

}

Комментарии:

1. Имеет смысл, но все равно не изменился таким образом