React触发Maximum update depth exceeded错误,移除moment后恢复求解释
问题原因拆解:无限渲染循环的根源
咱们一步步来分析你遇到的这个Maximum update depth exceeded错误:
1. 直接修改State的隐患
首先看你在handleIssueDate里的这段代码:
let fields = this.state.fields; fields["IssueDate"] = moment(date).format("YYYY-MM-DD") this.setState({ fields });
这里的fields是直接引用了this.state.fields的对象,你直接修改它的属性后再调用setState,这违反了React的状态不可变原则。虽然这不一定直接导致循环,但会让React的状态更新逻辑变得不可预测,可能间接引发问题。正确的做法应该是创建一个新对象:
let fields = {...this.state.fields}; // 浅拷贝原对象 fields["IssueDate"] = moment(date).format("YYYY-MM-DD") this.setState({ fields });
2. Datepicker属性类型不匹配导致的无限循环
这才是错误的核心原因:
你给Datepicker的selected和value属性传的是格式化后的字符串(比如"2024-05-20"),但绝大多数React日期选择组件(包括你用的这个)的selected属性要求传入的是Date对象或者moment对象,而不是字符串。
当你选择日期时:
onChange触发handleIssueDate,你把日期转成字符串存到state里,然后setState触发组件重新渲染- 重新渲染后,Datepicker拿到
selected的字符串值,它无法识别这个值和内部选中的日期是否匹配,就会认为“选中状态不一致”,于是再次触发onChange事件,把当前内部的Date对象传过来 - 这个过程不断重复:选日期→存字符串→渲染→Datepicker不识别→触发onChange→再存字符串→... 最终导致React检测到无限循环,抛出
Maximum update depth exceeded错误
3. 为什么移除moment格式化后就正常了?
当你去掉moment(date).format("YYYY-MM-DD"),直接把date(也就是Datepicker传入的Date/moment对象)存到state里时,selected属性的值类型和Datepicker期望的一致了。此时组件重新渲染后,Datepicker确认selected和内部状态匹配,就不会再次触发onChange,循环也就终止了。
修复建议
- 遵守React状态不可变原则,修改state时总是创建新对象/数组
- 给Datepicker的
selected属性传入正确类型的值(Date或moment对象),如果需要显示格式化后的日期,可以在组件的render里单独处理,或者用Datepicker自带的格式化属性(比如dateFormat)
内容的提问来源于stack exchange,提问作者user3166530
相关产品推荐
相关产品推荐

