javascript - 如何使用 React Hooks 更新不同的状态

标签 javascript reactjs react-hooks next.js

我正在使用 Vanta 制作背景组件在NextJS中,代码如下:

import { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import FOG from "vanta/dist/vanta.fog.min";
import { useDarkMode, useWindowSize } from "./Hooks";

const updateColor = (darkMode) => {
    return {
        highlightColor: darkMode ? 0xff0000 : 0xffd2c6,
        midtoneColor: darkMode ? 0xbe1d1d : 0xff7737,
        lowlightColor: darkMode ? 0x781212 : 0x69c3ff,
        baseColor: darkMode ? 0x0 : 0xffffff,
    }
}

export default function Background({ children }) {
    const [vantaEffect, setVantaEffect] = useState();
    //returns the width and height of the window
    const windowSize = useWindowSize();
    //user presses a button to change the theme from light to dark
    const [mode] = useDarkMode();
    const vantaRef = useRef();

    useEffect(() => {
        const isDark = mode === "dark";

        if (vantaEffect) {
            setVantaEffect(
                vantaEffect.setOptions({
                    minHeight: windowSize.height,
                    minWidth: windowSize.width,
                    ...updateColor(isDark)
                }));

            vantaEffect.resize();
        } else {
            setVantaEffect(
                FOG({
                    THREE,
                    el: vantaRef.current,
                    blurFactor: 0.18,
                    minHeight: window.innerHeight,
                    minWidth: window.innerWidth,
                    ...updateColor(isDark)
                })
            )
        }

        return () => {
            if (vantaEffect) vantaEffect.destroy();
        }
    }, [mode, windowSize]);

    return (
        <div>
            <div className="fixed -z-50" ref={vantaRef}></div>
            <div>{children}</div>
        </div>
    )
}

现在,如果模式或 windowSize 更新, Canvas 都将调整大小,并重新渲染为暗模式。我希望能够检测它是否是黑暗模式或正在调整大小的窗口是否运行了 useEffect 函数。

此外,每当我尝试检查该函数时,它都会要求我将vantaEffect 添加到依赖项中。当我这样做时,效果渲染了太多次并且滞后于页面。

有没有更好的方法使用钩子(Hook)来渲染背景?

最佳答案

要拆分 modewindowResize,您应该使用两个单独的 useEffect Hook 。通过将它们分开,这些 Hook 将仅在依赖项更新时执行。

我在您的代码中注意到,您在每次渲染时都执行 vantaEffect.destroy() 。我可能是错的,但我认为这不是你想要的。 如果您只想在 unmount 上执行此代码,则应添加另一个 useEffect,且其数组中不包含任何依赖项。 (如 React 文档中所述:

When exactly does React clean up an effect? React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.

https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1 )

总数看起来像这样:

    useEffect(() => {
        const isDark = mode === "dark";

        if (vantaEffect) {
            setVantaEffect(
                vantaEffect.setOptions({
                    ...updateColor(isDark)
                }));

            vantaEffect.resize();
        } else {
            setVantaEffect(
                FOG({
                    THREE,
                    el: vantaRef.current,
                    blurFactor: 0.18,
                    minHeight: window.innerHeight,
                    minWidth: window.innerWidth,
                    ...updateColor(isDark)
                })
            )
        }
    }, [mode]);

    useEffect(() => {
        if (vantaEffect) {
            setVantaEffect(
                vantaEffect.setOptions({
                    minHeight: windowSize.height,
                    minWidth: windowSize.width
                }));

            vantaEffect.resize();
        } else {
            setVantaEffect(
                FOG({
                    THREE,
                    el: vantaRef.current,
                    blurFactor: 0.18,
                    minHeight: window.innerHeight,
                    minWidth: window.innerWidth
                })
            )
        }
    }, [windowSize]);

    useEffect(() => {
        // only destroying the vantaEffect on unmount
        return () => vantaEffect?.destroy();
    }, []);

您应该优化输出,但我希望您明白这个想法

关于javascript - 如何使用 React Hooks 更新不同的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70366069/

相关文章:

reactjs - React 路由器交换机无法正常工作

reactjs - 使用 react-redux 翻译函数时呈现的钩子(Hook)比预期的少

javascript - 我无法理解这个 useEffect 如何通过 fetch 运行

javascript - 带有 ExtJS 的 ASP.NET MVC 3 返回错误的 json

javascript - 我可以通过从 PHP 获取变量来更改 Javascript 中的显示属性吗?

javascript - 英雄横幅轮播与 Gatsby + Contentful + react 响应式轮播

css - 在 React JS 中使用样式的最佳(最佳)方式

javascript - 使用钩子(Hook)设置事件类名

javascript - 使用 JQuery 从 JSON 文件中获取数据

javascript - Meteor 中的 jQuery 无法找到 DOM 选择器