useEffect запускается только при добавлении значения в массив, но не при удалении значения

#javascript #reactjs

#javascript #reactjs

Вопрос:

Итак, я новичок в React и пытаюсь создать базовое приложение расписания. У меня есть четыре файла: «App.js «, «AllEvents.js «, «Event.js «, и «NavBar.js «

Мой App.js это довольно просто, и я включил только соответствующие части

 const App = () => {
  const [eventFilters, setEventFilters] = useState([]);
  const [allEvents, setAllEvents] = useState([]);

  useEffect(() => {
    getAllEvents();
  }, []);

  const getAllEvents = async () => {
    const response = await fetch(URL);
    const data = await response.json();

    setAllEvents(data.events);
  };

  return (
    <div className="App">
      <NavBar eventFilters={eventFilters} setEventFilters={setEventFilters}/>
      <AllEvents allEvents={allEvents} eventFilters={eventFilters}/>
    </div>
  )
} 
  

В AllEvents.js Я на самом деле визуализирую события, которые я получаю от getAllEvents() в App.js

 import React, { useState, useEffect } from 'react';
import Event from './Event';

const AllEvents = ({allEvents, eventFilters}) => {
  const [filteredEvents, setFilteredEvents] = useState([]);

  const getFilteredEvents = () => {
    setFilteredEvents(allEvents.filter(event => eventFilters.includes(event.eventType)));
  }

  useEffect(() => {
      getFilteredEvents();
  }, [eventFilters.length]);

  return(
    <div>
        {filteredEvents.map((event) => (
            <Event 
              key={event.id}
              title={event.name}
              description={event.description}
              type={event.eventType}
            />
        ))}
    </div>
  );
}
  

В NavBar.js Я устанавливаю фильтры событий в зависимости от того, какие кнопки нажаты

 const navBar = ( {eventFilters, setEventFilters} ) => {
  const eventFilterHandler = (e) => {
    var passedFilter = e.target.value;
    var arrayContainsFilter = false;

    for(var i = 0; i < eventFilters.length; i  ){
      if(eventFilters[i] == passedFilter){
        eventFilters.splice(i, 1);
        setEventFilters(eventFilters);
        arrayContainsFilter = true;
      }
    }

    if(!arrayContainsFilter){
      setEventFilters(eventFilters.concat(passedFilter));
    }
    console.log(eventFilters);
  };

  return(
    <div>
      
      <div onClick={eventFilterHandler}>
        <button value="ALL"> All </button>
        <button value="WORKSHOP"> Workshop </button>
        <button value="MINIEVENT"> Minievent </button>
        <button value="SPEAKER"> Speaker </button>
        <button value="MEAL"> Meal </button>
        <button value="OTHER"> Other </button>
      </div>

    </div>
  );
}
  

Когда я добавляю значения в eventFilters, нажимая на кнопки, useEffect в AllEvents.js запускает и повторно отображает страницу. Однако, когда я удаляю значения, useEffect не запускается, и страница не отображается повторно. Кто-нибудь знает почему?

Ответ №1:

Проблема в том:

 for(var i = 0; i < eventFilters.length; i  ){
  if(eventFilters[i] == passedFilter){
    eventFilters.splice(i, 1);
    setEventFilters(eventFilters);
    arrayContainsFilter = true;
  }
}

if(!arrayContainsFilter){
  setEventFilters(eventFilters.concat(passedFilter));
}
  

В цикле вы изменяете существующее состояние (никогда не делайте этого в React!) и передаете измененное состояние функции set state . Поскольку старое состояние === переходит в новое состояние, повторный рендеринг отсутствует.

Никогда не изменяйте состояние в React. Вместо этого создайте копию. Здесь вы можете использовать filter :

 if (eventFilters.includes(passedFilter)) {
  setEventFilters(
    eventFilters.filter(item => item !== passedFilter)
  );
} else {
  setEventFilters(eventFilters.concat(passedFilter));
}
  

Ответ №2:

Насколько я понимаю, вы хотите повторно отобразить компонент после изменения данных.Но он изменяется только при добавлении данных, а не при их удалении.Это может быть связано с тем, что useEffect вы запускаете его только при получении данных.Ранее

 useEffect(() => {
    getAllEvents();
  }, []);
  

Теперь

  useEffect(() => {
    getAllEvents();
  }, [allEvents]);
  

Запустите useEffect при изменении данных.Если оно удалено или добавлено