首页 > 解决方案 > useEffect 仅在将值添加到数组时运行,但在删除值时不运行

问题描述

所以我是 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 中,我实际上渲染了从 App.js 中的 getAllEvents() 获得的事件

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 中,我根据按下的按钮设置 eventFilters

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 添加值时,AllEvents.js 中的 UseEffect 会运行并重新呈现页面。但是,当我删除值时,useEffect 不会运行并且页面不会重新呈现。有人知道为什么吗?

标签: javascriptreactjs

解决方案


问题是:

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

推荐阅读