[英]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])
要拆分mode
和windowResize
,您应该使用两个单独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.