React类分页组件报Maximum update depth exceeded错误,请求代码问题排查
React分页触发「最大更新深度超限」报错排查
报错根本原因
- 你遇到的报错和是否在
componentWillUpdate、componentDidUpdate里写setState没有直接绑定关系,只要是组件渲染的同步执行路径上存在无条件的setState调用,就会触发无限更新循环。 - 你的代码调用链路是:组件执行
render→ 执行render里的pagincationScript方法 → 方法内部立刻执行this.setState({li: li})→ 触发组件重渲染 → 再次执行render、再次调用pagincationScript、再次触发setState……循环往复,最终触发React的无限更新保护机制抛出错误。 - 哪怕你把setState放在for循环之后,只要这段代码是每次渲染都会执行的,和你在for循环哪个位置写setState没有关系,循环是必然触发的。
代码存在的其他问题
- 分页的li标签属于纯UI渲染计算结果,完全不需要存入组件state,把这类计算结果存到state会额外触发不必要的组件重渲染,增加性能损耗。
- 即使不触发循环,由于setState是异步更新的,你在调用完setState后立刻读取
this.state.li拿到的依然是上一次渲染的旧值,根本不是刚push完成的最新列表。 - 组件命名不统一:类定义时的组件名是
Pagination,导出时却写为PagePagination,会导致外部引用时无法正确拿到组件实例。 - 按钮类名拼写错误:Next按钮的className误写为
Btn Previous,会导致样式匹配错误。 - 方法名拼写错误:
pagincationScript存在拼写偏差,长期维护容易出现调用错误。
修正后的可运行代码
// React import React, { Component } from 'react' class Pagination extends Component { liTags = (pageNum) => { return <li className="PageNumber" key={pageNum}><span>{pageNum}</span></li> } paginationScript = (totalPages, page) => { // 直接在渲染阶段计算分页列表,不存入state const liList = [] for(let i = 1; i < totalPages; i++){ liList.push(this.liTags(i)) } if(page > 1 && page < totalPages){ return ( <React.Fragment> <li className="Btn Previous"><span><i>←</i>Previous</span></li> {liList} <li className="Btn Next"><span><i>→</i>Next</span></li> </React.Fragment> ) } } render() { return ( <div className="Pagination"> <ul> {this.paginationScript(10, 5)} </ul> </div> ) } } export default Pagination;
补充说明:如果后续需要根据用户操作动态修改当前页码,只需要把页码本身存入state即可,分页标签列表依然可以在render阶段通过页码计算得出,不需要把整个标签列表存入state。
内容的提问来源于stack exchange,提问作者night_programmer
相关产品推荐
相关产品推荐

