我正在使用 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)来渲染背景?
最佳答案
要拆分 mode
和 windowResize
,您应该使用两个单独的 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/