我想通过在useEffect内将窗口位置设置回其先前状态来滚动到我先前的窗口位置。为了获得以前的状态,我正在使用useRef。
该组件曾经是基于类的,因此可以完美地工作。在将其重构为钩子之后,这种“不稳定”的行为开始了。
在开始处声明useRef
const scrollRef = useRef(window.pageYOffset);
每当重新渲染组件时:
scrollRef.current = window.pageYOffset;
状态更新时:
useEffect(() => {
window.scrollTo(0, scrollRef.current)
});
完整代码:
export default () => {
const scrollRef = useRef(window.pageYOffset);
...
scrollRef.current = window.pageYOffset;
useEffect(() => {
window.scrollTo(0, scrollRef.current)
});
return (
...
);
}
在状态更新时,我想通过不具有这种“不稳定”的行为来变回到先前的窗口位置。 (通过摇晃,我的意思是看起来他滚动到顶部,然后又滚动到先前的位置,所以看起来好像在晃动)
答案 0 :(得分:0)
您的问题的解决方案如下所示:
首先创建一个自定义usePrevious
挂钩。这只是另一个函数,它使用新的useRef
方法存储以前的滚动值,并且仅在将新值传递给它时才对其进行更新。
// Hook
function usePrevious(value) {
// The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class
const ref = useRef();
// Store current value in ref
useEffect(() => {
ref.current = value;
}, [value]); // Only re-run if value changes
// Return previous value (happens before update in useEffect above)
return ref.current;
}
在实际组件中,我们声明一个previousPosition
变量。每次重新渲染组件时,都会使用当前位置执行我们的customHook。它返回之前的位置,然后将其分配。
对于每个渲染,也将执行useEffect
方法,因为我们没有将Array作为第二个参数传递。在那里,我们只是将当前滚动位置与
前一个,然后滚动回前一个,以防更改。
function Scroll(props){
const prevPosition = usePrevious(window.pageYOffset);
// Update scoll position with each update
useEffect(() => {
if(window.pageYOffset !== prevPosition){
window.scrollTo(0, prevPosition);
}
});
return (
<div>
...
</div>
);
}
答案 1 :(得分:0)
如果我理解正确,请使用useLayoutEffect
代替useEffect
。在呈现组件之前,它将滚动回到顶部。记住要添加依赖项数组。