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

React基于过滤条件重渲染数组出现过多重渲染错误如何解决?

问题修复方案

错误根因

你在组件函数的顶级作用域直接调用setTasks修改状态,触发了死循环:

  • React组件每次渲染都会执行函数内所有顶级代码
  • 只要showAll为false,就会执行setTasks更新状态
  • 状态更新会触发组件重新渲染,又会再次执行到这段setTasks逻辑,无限循环导致过多重渲染报错
    另外直接修改原始tasks状态会覆盖接口返回的全量数据,后续切换回「展示全部」时也无法恢复完整任务列表。

修复步骤

保留原始tasks状态存储全量接口数据,不要直接修改它,渲染前基于showAll的状态动态计算要展示的任务列表即可,无需额外维护状态。

修正后的代码

const MainPage = () => {
    const [tasks, setTasks] = useState([]); 
    const [showAll, setShowAll] = useState(true);  

    useEffect( ()=> {
        axios.get('api/tasks/')
            .then( response => {
                setTasks(response.data.tasks); 
            })
            .catch(err => {
                console.log('error');
            })
    }, []);

    const fetchItems = (cat_id) => {  
        axios.get('/api/tasks/')
        .then( response => {
                setTasks(response.data.tasks);
        })
        .catch(err => {
            console.log('error');
        })
    }; 

    const handleCheckboxChange = (e) => {
        // 注意setShowAll是异步更新,此处打印的showAll为更新前的旧值
        setShowAll(!showAll)
    };
    
    // 动态计算要展示的任务列表,不修改原始状态
    const displayedTasks = showAll ? tasks : tasks.filter(v => !v.completed);

    return (
        <div>
           <label className="checkb">
                <input 
                name="show_all"
                id="show_all"
                type="checkbox"
                checked={showAll}
                onChange={handleCheckboxChange}
                /> 展示全部
            </label>

            <br/>
            { displayedTasks && displayedTasks.map((task, index) => {
                return (
                    <div key={index} className="task-wrapper flex-wrapper">
                        <div > 
                                { !task.completed ? (
                                <span> {index +1}. {task.task_description} </span> ) : 
                                (<strike> {index +1}. {task.task_description} </strike>)  }                               
                        </div>
                        <div>
                            <button 
                                onClick={()=> modalClick(task)}
                                className="btn btn-sm btn-outline-warning">编辑</button>
                            <span> &nbsp;  </span>
                        </div>
                    </div>
                )
                })}
        </div>
    );
};

export default MainPage;

可选优化点

如果任务列表数据量很大,可以用useMemo缓存计算结果,避免每次渲染都重新过滤:

const displayedTasks = useMemo(() => {
  return showAll ? tasks : tasks.filter(v => !v.completed)
}, [showAll, tasks])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:24:03