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
相关产品推荐
相关产品推荐

