React中setState引发函数重复执行及无限渲染问题求助
解决React明暗模式切换的无限重渲染问题
问题根源
你直接在组件函数体内调用setDark(localDark),每次组件渲染时这段代码都会执行,而setDark会触发组件重新渲染,于是陷入「渲染→调用setDark→重新渲染→再次调用setDark」的无限循环,最终触发React的渲染次数限制报错。
修正方案
1. 用函数式初始值初始化状态
把useState的初始值改成从localStorage读取的函数,这样只会在组件第一次初始化时执行一次读取操作,不会每次渲染都触发:
const [dark, setDark] = useState(() => { const savedDark = localStorage.getItem("dark"); return savedDark !== null ? JSON.parse(savedDark) : false; });
2. 优化点击事件逻辑
原来的点击事件里,localStorage.setItem存的是修改前的状态值,用setDark的回调形式可以确保拿到最新状态,同时同步localStorage和body类名:
const onClick = () => { setDark(prevDark => { const newDark = !prevDark; localStorage.setItem("dark", newDark); // 用toggle简化类名操作 document.body.classList.toggle("dark", newDark); return newDark; }); };
3. 移除组件内的if判断代码
删掉原来那个直接调用setDark的if代码块,因为初始状态已经通过useState的函数式参数处理了localStorage的读取。
4. 用useEffect同步body类名(可选但推荐)
如果页面刷新或外部修改localStorage时,确保body类名和状态一致,添加useEffect监听状态变化:
useEffect(() => { document.body.classList.toggle("dark", dark); }, [dark]);
完整修正代码
import { useState, useEffect } from 'react'; function Mode() { const [dark, setDark] = useState(() => { const savedDark = localStorage.getItem("dark"); return savedDark !== null ? JSON.parse(savedDark) : false; }); const onClick = () => { setDark(prevDark => { const newDark = !prevDark; localStorage.setItem("dark", newDark); return newDark; }); }; useEffect(() => { document.body.classList.toggle("dark", dark); }, [dark]); return ( <div onClick={onClick} className="mode"> {dark ? <Light /> : <Dark />} </div> ); }
内容的提问来源于stack exchange,提问作者tices
相关产品推荐
相关产品推荐

