[英]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.