You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React DayPicker无限循环/无值问题:无法渲染选中日期的生日列表

React DayPicker 选日期后过滤生日数据触发无限循环问题

现有应用可匹配生日数组与当日日期,计划扩展功能:通过React DayPicker选择任意日期,展示对应生日信息。目前console.log能输出预期结果,但调用setListWriter会触发无限循环,页面渲染时listWriter无有效值,无法正常展示目标内容。

当前代码:

import React, { useState } from 'react';
import { DayPicker } from 'react-day-picker';
import data from './writers-birthday-array.json';

function PickDate() {

  const [selected, setSelected] = useState();
  const [matchDate, setMatchDate] = useState(data);
  const [listWriter, setListWriter] = useState([]);

  if (selected) {
    let formattedDate =
      ('0' + selected.getDate()).slice(-2) + `/` + (selected.getMonth() + 1);

    const listedWriter = matchDate.filter(
      (writer) => writer.birthday === formattedDate
    );


    //setListWriter(listedWriter); -> this will cause an infinite loop


    console.log(formattedDate); //correct value
    console.log(listedWriter); // this is the value I want to display on the page
  }

  return (
    <main>
      <section className="container">
        <div>
          <h3>Pick a date</h3>
          <DayPicker
            mode="single"
            selected={selected}
            onSelect={setSelected}    
          />
        </div>
     
        {listWriter ? <div> {listWriter} </div> : <div></div>}
        //here listWriter has no value     
     </section>
    </main>
  );
}

export default PickDate;

使用的日期选择器包:react-day-picker
原有作家展示模块运行正常。


问题原因

直接在组件渲染逻辑里调用setListWriter状态更新函数:每次组件渲染时,只要selected有值就会执行这段代码,状态更新会触发组件重新渲染,重新渲染又会再次执行代码,形成无限循环。

解决方案

方案1:使用useEffect监听selected变化

这是最推荐的方式,把过滤逻辑放到useEffect钩子中,仅当selected改变时执行:

import React, { useState, useEffect } from 'react';
import { DayPicker } from 'react-day-picker';
import data from './writers-birthday-array.json';

function PickDate() {
  const [selected, setSelected] = useState();
  const [listWriter, setListWriter] = useState([]);

  // 只有selected变化时才执行过滤逻辑
  useEffect(() => {
    if (selected) {
      const formattedDate = ('0' + selected.getDate()).slice(-2) + `/` + (selected.getMonth() + 1);
      // 直接用原始data,不需要存到matchDate状态里
      const listedWriter = data.filter(writer => writer.birthday === formattedDate);
      setListWriter(listedWriter);
    }
  }, [selected]);

  return (
    <main>
      <section className="container">
        <div>
          <h3>Pick a date</h3>
          <DayPicker
            mode="single"
            selected={selected}
            onSelect={setSelected}    
          />
        </div>
     
        {/* 空数组[]在布尔判断里为true,所以要判断长度 */}
        {listWriter.length > 0 ? (
          <div>
            {/* 遍历数组展示具体内容,根据你的数据结构调整字段 */}
            {listWriter.map(writer => (
              <div key={writer.id}>{writer.name}</div>
            ))}
          </div>
        ) : (
          <div>暂无对应生日的作家</div>
        )}
     </section>
    </main>
  );
}

export default PickDate;

说明:

  • 移除了matchDate状态,因为原始数据data是固定的,直接使用即可,没必要存在状态中
  • useEffect的依赖数组里只放selected,确保只有选中日期变化时才执行过滤和状态更新
  • 渲染时判断数组长度,避免空数组时显示错误内容,同时用map遍历展示具体作家信息

方案2:直接在渲染时计算结果(无需状态)

如果过滤逻辑简单,也可以直接在JSX中计算结果,不用额外状态存储:

import React, { useState } from 'react';
import { DayPicker } from 'react-day-picker';
import data from './writers-birthday-array.json';

function PickDate() {
  const [selected, setSelected] = useState();

  return (
    <main>
      <section className="container">
        <div>
          <h3>Pick a date</h3>
          <DayPicker
            mode="single"
            selected={selected}
            onSelect={setSelected}    
          />
        </div>
     
        {selected ? (
          (() => {
            const formattedDate = ('0' + selected.getDate()).slice(-2) + `/` + (selected.getMonth() + 1);
            const listedWriter = data.filter(writer => writer.birthday === formattedDate);
            return listedWriter.length > 0 ? (
              <div>
                {listedWriter.map(writer => <div key={writer.id}>{writer.name}</div>)}
              </div>
            ) : <div>暂无对应生日的作家</div>;
          })()
        ) : <div>请选择日期</div>}
     </section>
    </main>
  );
}

export default PickDate;

这种方式省去了状态更新的步骤,但如果过滤逻辑复杂,多次渲染会重复计算,性能不如第一种方案。


内容的提问来源于stack exchange,提问作者HungryOctopus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 11:35:17