useEffect中使用的所有变量都需要指定为依赖项吗?
我的用例(出于演示目的而简化(涉及根据浏览器窗口的宽度执行的不同功能,但在浏览器窗口更改时不会运行:
const scrollToTop = () => window.scrollTo(0, 0)
const scrollToTopOfArticle = () => window.scrollTo(0, 200)
function App({
isDesktop,
selectedArticle
}) {
useEffect(() => {
isDesktop ? scrollToTop() : scrollToTopOfArticle()
}, [selectedArticle])
return (
<div className="App">
<h1>{selectedArticle.title}</h1>
<p>{selectedArticle.body}</p>
</div>
);
}
如果我将isDesktop添加到依赖项中,那么每当用户在移动和桌面之间调整窗口大小时,效果就会运行,这是不希望的,但我也知道效果中使用的所有东西都必须列为依赖项。
关于如何协调这两个要求,有什么建议吗?
如果要使useEffect()
仅响应selectedArticle
的更改,请使用isDesktop
和selectedArticle
初始化组件状态。每当selectedArticle
发生更改时,第一个useEffect()
将使用传入的道具更新这两种状态,并触发第二个useEffect()
在下一次渲染时重新运行。
const scrollToTop = () => window.scrollTo(0, 0)
const scrollToTopOfArticle = () => window.scrollTo(0, 200)
function App({
isDesktop,
selectedArticle
}) {
const [desktop, setDesktop] = useState(isDesktop)
const [article, setArticle] = useState(selectedArticle)
useEffect(() => {
if (article !== selectedArticle) {
setDesktop(isDesktop)
setArticle(selectedArticle)
}
}, [isDesktop, selectedArticle, article])
useEffect(() => {
if (desktop) scrollToTop()
else scrollToTopOfArticle()
}, [desktop, article])
return (
<div className="App">
<h1>{selectedArticle.title}</h1>
<p>{selectedArticle.body}</p>
</div>
)
}
或者,您可以将这种锁存行为抽象到另一个钩子,以便isDesktop
仅在selectedArticle
更改时更新为其活动值。注意,selectedArticle
仍然需要是滚动动作效果的依赖项,因此即使isDesktop
自上次触发以来没有改变值,useEffect()
也会在每次更改selectedArticle
时触发滚动动作。
const useLatch = (value, deps) => {
const [state, setState] = useState(value)
const effect = useCallback(() => { setState(value) }, [value])
useEffect(effect, deps)
return state
}
const scrollToTop = () => window.scrollTo(0, 0)
const scrollToTopOfArticle = () => window.scrollTo(0, 200)
function App({
isDesktop,
selectedArticle
}) {
const latchedIsDesktop = useLatch(isDesktop, [selectedArticle])
useEffect(() => {
if (latchedIsDesktop) scrollToTop()
else scrollToTopOfArticle()
}, [latchedIsDesktop, selectedArticle])
return (
<div className="App">
<h1>{selectedArticle.title}</h1>
<p>{selectedArticle.body}</p>
</div>
)
}
useEffect中的所有变量都必须作为依赖项列出吗?
是,否则将生成警告。
这就是为什么最好清楚地知道每种效果应该做什么(即分离关注点(。
因此,您可以有两个具有不同依赖关系的独立效果。
类似于:
useEffect(
() => {
scrollToTopOfArticle();
}, [selectedArticle]
);
useEffect(
() => {
if (selectedArticle && isDesktop) {
scrollToTop();
}
}, [isDesktop, selectedArticle]
)