【问题标题】:useEffect keep fetching my data if I add state in useEffect如果我在 useEffect 中添加状态,useEffect 会继续获取我的数据
【发布时间】:2023-03-28 13:00:03
【问题描述】:

当我在这样的数组中将 eventList 添加到我的 useEffect 中时:

  const getEvents = async () => {
    const res = await axios.get(`/api/v1/events/event/${teamId}`);

    setEventList(res.data.Events);
  };

  useEffect(() => {
    getEvents();
  }, [eventList]);

它只是不停地获取数据

但是如果我不把 eventList 放在那里,我的页面只需获取一次,当我点击另一个组件时就会消失

添加的组件:

日历.js:

const Calendar = (props) => {
  const { teamId } = props;
  const events = [];
  const [date, setDate] = useState(new Date());
  const [eventList, setEventList] = useState([]);
  const [expanded, setExpanded] = useState("");

  const getEvents = async () => {
    const res = await axios.get(`/api/v1/events/event/${teamId}`);

    setEventList(res.data.Events);
  };

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

  const handleChangeAccordion = (panel) => (event, newExpanded) => {
    setExpanded(newExpanded ? panel : false);
  };

  const handleChangeCalendar = (value) => {
    const currentDate = moment(value).format("YYYY-MM-DD");
    setDate(currentDate);
    const currentEvents = events.find((event) =>
      moment(currentDate).isSame(event.date, "day")
    );
    setEventList(currentEvents ? currentEvents.events : []);
  };

  const [showCalendarCard, setShowCalendarCard] = useState(false);

  const addEvent = () => {
    setShowCalendarCard(true);
  };

  return (
    <div className="calendar-tab">
      <div className="event-view-container">
        <div className="event-date">
          <p className="event-date-monthday">{moment(date).format("D")}</p>
          <p className="event-date-weekday">{moment(date).format("dddd")}</p>
        </div>
        <div className="event-list">
          {eventList.map((event, index) => (
            <div>
              <Accordion
                key={`event-${index}`}
                square
                expanded={expanded === `event${index + 1}`}
                onChange={handleChangeAccordion(`event${index + 1}`)}
              >
                <AccordionSummary>
                  <div className="event-list-item-header">
                    <span className="timestart">
                      {moment(event.timestart, "HH:mm:ss").format("h:mm A")}
                    </span>
                    <span className="dash">-</span>
                    <span className="timeend">
                      {moment(event.timeend, "HH:mm:ss").format("h:mm A")}
                    </span>
                    <span className="title">{event.title}</span>
                  </div>
                </AccordionSummary>
              </Accordion>
              <div className="event-list-item-content">
                <div className="header">
                  <span className="announcements">Announcements</span>
                  <div className="plus">
                    <ControlPoint />
                  </div>
                </div>
                <div className="content">{event.description}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
      <div className="calendar-view-container">
        <div className="event-calendar-container">
          {!showCalendarCard ? (
            <div>
              <EventCalendar
                className="event-calendar"
                formatShortWeekday={(locale, date) =>
                  moment(date).format("dd").charAt(0)
                }
                tileClassName={({ date }) => {
                  if (events.find((x) => moment(x.date).isSame(date, "day"))) {
                    return "highlight";
                  }
                }}
                onChange={(value) => handleChangeCalendar(value)}
                nextLabel={<NavigateNext />}
                prevLabel={<NavigateBefore />}
              />
              <div className="add-event">
                <ControlPoint onClick={addEvent} />
              </div>
            </div>
          ) : (
            <CalendarCard
              setShowCalendarCard={setShowCalendarCard}
              teamId={teamId}
            />
          )}
        </div>
      </div>
    </div>
  );
};

export default Calendar;

当我点击日历中的另一天时,它会显示我的事件列表。

这是我项目的照片:

【问题讨论】:

  • 我建议使用某种计时器,而不是将 React 置于无限循环中。
  • @DBS 我该怎么做?
  • 有一些体面的问题涵盖了这种事情,例如Polling api every x seconds with react

标签: reactjs


【解决方案1】:

您的 useEffect 取决于 eventList 进行更改,并且通过调用该函数您正在更改 eventList,如果您只想发送一次请求,那么这个解决方案就可以了

const Calendar = (props) => {
  const { teamId } = props;
  // const events = [];
  const [date, setDate] = useState(new Date());
  const [eventList, setEventList] = useState([]);
  const [expanded, setExpanded] = useState("");

  const getEvents = async () => {
    const res = await axios.get(`/api/v1/events/event/${teamId}`);

    setEventList(res.data.Events);
  };

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

有一个空的依赖列表只会触发一次函数,所以改变

useEffect(() => {
    getEvents();
  }, [eventList]);

到这里

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

【讨论】:

  • 但是如果我换成其他组件时只调用一次它就会消失
  • 你能编辑你的问题并添加组件吗?
  • 我刚刚编辑了它。因此,当我单击日历中的另一天时,数据将消失,当我单击返回创建日期时,它仍然消失
【解决方案2】:

它卡在一个循环中,因为您的 useEffect 回调具有改变它自己的依赖关系 (eventList) 的副作用。

基本上不是重置您从 API 获取的事件列表,而是记住过滤后的列表

例如

const filteredEventList = useMemo(() => {
  return eventList.filter((event) =>
      moment(date).isSame(event.date, "day")
    )
}, [date, eventList])

然后在你的渲染中使用这个过滤的事件列表

【讨论】:

  • 我该如何解决这个问题?
  • 你需要更好地组织你的代码。避免在用户输入内容时点击 API。我会更详细地编辑。
  • 更新了,看看吧。
猜你喜欢
  • 2020-04-08
  • 2021-11-01
  • 2021-03-13
  • 1970-01-01
  • 2022-01-15
  • 2020-12-11
  • 2022-07-07
  • 1970-01-01
  • 2022-01-04
相关资源
最近更新 更多