React Native报Too many re-renders错误怎么解决?跨页传日期给DayColoumns
问题解答
核心问题根因
你触发无限重渲染的原因非常明确:你在ScreenPlanner组件的顶层作用域直接调用了setSelectedDate。
React组件每次渲染时都会执行组件内部所有顶层代码,setSelectedDate调用会更新state,state更新又会触发组件重新渲染,往复循环就触发了React的重渲染次数限制报错。
另外你最初的顾虑也不成立:React Navigation默认是懒加载路由页面的,只有你从SelectionScreen跳转过来的时候,ScreenPlanner才会开始渲染,此时route.params.date已经是用户选择完成的有效值,不需要提前渲染所有页面。
最优解决方案(无需额外维护state)
你已经可以通过route.params拿到传递过来的日期,完全不需要额外用state存储一份,直接使用即可,直接删掉冗余的state和顶层的setState调用就行。
修正后的代码如下:
const ScreenPlanner = ({ route }) => { // 直接从route.params拿日期,加个默认值兜底 const selectedDate = route.params?.date || new Date(); // 用useMemo缓存计算结果,只有selectedDate变化时才重新计算,避免不必要的性能损耗 const flatListData = React.useMemo(() => { console.log("Date " + selectedDate); let dates = []; let data = []; let day = new Date(selectedDate); console.log("day " + day); let nextDay = new Date(day); // 生成未来7天的日期 for (let i = 0; i < 7; i++) { dates.push(new Date(nextDay.setDate(day.getDate() + i))); } const locale = "de-DE"; let options = { weekday: "short", year: "numeric", month: "long", day: "numeric", }; dates.forEach((date) => { data.push({ id: moment(date).format("DD/MM/YYYY"), day: date.toLocaleString(locale, options).substring(0, 3).toUpperCase(), number: date.getDate(), }); }); return data; }, [selectedDate]); // 依赖项是selectedDate,只有它变的时候才重新执行计算 return ( <View style={styles.screen}> <Header style={styles.header}> <Text style={styles.text}>{selectedDate}</Text> </Header> <View style={styles.containerPlanner}> <View style={styles.dayColoumns}> <FlatList horizontal={true} keyExtractor={(item, index) => item.id} data={flatListData} renderItem={(itemData) => ( <DayColoumns id={itemData.item.id} day={itemData.item.day} number={itemData.item.number} /> )} /> </View> <View style={styles.containerHourRows}> <HourRows /> </View> </View> </View> ); };
如果确实需要维护SELECTEDDATE状态的写法
如果后续你有在当前页面修改日期的需求,确实需要用state存储,那请把state更新逻辑放到useEffect里,只有当route.params.date变化的时候才更新state:
const [SELECTEDDATE, setSelectedDate] = useState(route.params?.date || new Date()); useEffect(() => { if(route.params?.date) { setSelectedDate(route.params.date); } }, [route.params?.date]); // 仅当route.params.date变化时才执行更新
额外优化建议
- 循环变量i请加
let声明,避免变成全局变量污染 - 日期格式化逻辑如果多处使用,可以抽成公共工具函数复用
内容的提问来源于stack exchange,提问作者Daniel Scho
相关产品推荐
相关产品推荐

