【问题标题】:Why does using setState in React makes function repeat?为什么在 React 中使用 setState 会使函数重复?
【发布时间】:2023-01-22 05:10:54
【问题描述】:

有一个按钮可以切换暗模式和亮模式,所以我试图在localStorage 中保存它所处模式的状态。但是,当我尝试将状态更改为 React 函数内的任何状态时,它会无限调用该函数并给出此错误: Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

如何在不无限地重新渲染函数的情况下更改状态?

let localDark = localStorage.getItem("dark");

function Mode() {
    const [dark, setDark] = useState(false);

    const onClick = () => {
        if (dark) {
            setDark(false);
            document.querySelector("body").classList.remove("dark");
        } else {
            setDark(true);
            document.querySelector("body").classList.add("dark");
        }
        localStorage.setItem("dark", dark);
    };

    if (localDark !== null) {
        localDark = JSON.parse(localStorage.getItem("dark"));
        setDark(localDark); // this is what causes the error
        // onClick();
    }

    return (
        <div onClick={onClick} className="mode">
            {dark ? <Light /> : <Dark />}
        </div>
    );
}

【问题讨论】:

  • 你好!我对 React 不是很好,所以请对我所说的持怀疑态度,但我认为这是因为 darksetDark 直接相关。也许使用setDark(!dark)?我不确定。

标签: javascript reactjs jsx setstate


【解决方案1】:

在 React 中使用 setState 会导致函数重复,因为它触发了组件的重新渲染。

为防止这种情况,您应该使用带有空数组的 useEffect 挂钩作为依赖项来设置组件安装时的状态。这样,状态只会被设置一次,useEffect 钩子不会触发重新渲染。

【讨论】:

    【解决方案2】:

    您遇到的问题是因为 if (localDark !== null) 块内的 setDark(localDark) 行导致组件重新渲染,然后再次触发 if (localDark !== null) 块,导致一个无限循环。

    要解决此问题,您可以使用 useEffect 挂钩来处理本地存储逻辑。 useEffect 挂钩允许您在组件呈现后运行副作用,例如设置订阅或手动更改 DOM。

    以下是如何更新代码以使用 useEffect 的示例:

    function Mode() {
    const [dark, setDark] = useState(false);
    
    const onClick = () => {
        if (dark) {
            setDark(false);
            document.querySelector("body").classList.remove("dark");
        } else {
            setDark(true);
            document.querySelector("body").classList.add("dark");
        }
        localStorage.setItem("dark", dark);
    };
    
    useEffect(() => {
        const localDark = JSON.parse(localStorage.getItem("dark"));
        if (localDark !== null) {
            setDark(localDark);
        }
    }, []);
    
    return (
        <div onClick={onClick} className="mode">
            {dark ? <Light /> : <Dark />}
        </div>
    );
    

    }

    这样,逻辑只在组件第一次渲染时运行一次,因此避免了无限循环。

    此外,您还可以将 dark 作为第二个参数传递给 useEffect 钩子,这样效果只会在黑暗状态发生变化时运行,这样效果只会在黑暗状态发生变化时运行,这将防止无限循环。

    useEffect(() => {
    const localDark = JSON.parse(localStorage.getItem("dark"));
    if (localDark !== null) {
        setDark(localDark);
    }
    

    }, [黑暗的]);

    这样,效果只会在黑暗状态发生变化时运行,这将防止无限循环。

    【讨论】:

      猜你喜欢
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 2020-08-22
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 2020-07-15
      相关资源
      最近更新 更多