簡體   English   中英

如何使用 React Hooks 更新不同的狀態

[英]How to use React Hooks to update different states

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

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>
    )
}

現在,如果更新了 mode 或 windowSize,canvas 將同時調整大小,並為暗模式重新渲染。 我希望能夠檢測它是暗模式還是正在調整大小的 window 運行 useEffect function。

此外,每當我嘗試對 function 進行 lint 處理時,它都會要求我將vantaEffect 添加到依賴項中。 當我這樣做時,效果會渲染太多次並滯后於頁面。

有沒有更好的方法來使用鈎子來渲染背景?

我希望能夠檢測它是暗模式還是正在調整大小的 window 運行 useEffect function。

您可以在組件中使用兩種效果,一種用於mode ,另一種用於windowSize

此外,每當我嘗試對 function 進行 lint 處理時,它都會要求我將vantaEffect 添加到依賴項中。 當我這樣做時,效果會渲染太多次並滯后於頁面。

您可以使用功能 state 更新來訪問以前的 state:

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

    setVantaEffect((previousVantaEffect) => {
       // use `previousVantaEffect` and return what you want
    })

}, [mode])

要拆分modewindowResize ,您應該使用兩個單獨useEffect掛鈎。 通過拆分它們,這些鈎子將僅在更新依賴項時執行。

我在您的代碼中注意到的是,您在每次渲染時都執行vantaEffect.destroy() 我可能弄錯了,但我認為這不是你想要的。 如果您只想在unmount時執行此代碼,您應該在其數組中添加另一個useEffect ,而不需要任何依賴項。 (如 React 文檔中所述:

React 究竟何時清理效果? React 在組件卸載時執行清理。 然而,正如我們之前所了解的,效果會為每次渲染運行,而不僅僅是一次。 這就是為什么 React還會在下次運行效果之前清理上一次渲染中的效果。

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();
    }, []);

你應該優化 output,但我希望你明白

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM