最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Restore scroll position in React Hooks with useRef is shaky - Stack Overflow

programmeradmin3浏览0评论

I want to scroll to my previous window position by setting inside a useEffect the window position back to its previous state. To get the previous state, I am using useRef.

The Component was once class-based and there it worked perfectly. After I refactored it to hooks, this "shaky" behavior started.

Declaring the useRef right at the beginning

const scrollRef = useRef(window.pageYOffset);

Whenever the ponent re-renders:

scrollRef.current = window.pageYOffset;

When the state gets updated:

useEffect(() => {
  window.scrollTo(0, scrollRef.current)
});

The Complete Code:

export default () => {
   const scrollRef = useRef(window.pageYOffset);
   ...
   scrollRef.current = window.pageYOffset;
   useEffect(() => {
      window.scrollTo(0, scrollRef.current)
   });

   return (
      ...
   );
}

On state update, I want to change back to the previous window position by not having this "shaky" behavior. (By shaky I mean it looks like he scrolls to the top and right after to the previous position so it looks like it shakes)

I want to scroll to my previous window position by setting inside a useEffect the window position back to its previous state. To get the previous state, I am using useRef.

The Component was once class-based and there it worked perfectly. After I refactored it to hooks, this "shaky" behavior started.

Declaring the useRef right at the beginning

const scrollRef = useRef(window.pageYOffset);

Whenever the ponent re-renders:

scrollRef.current = window.pageYOffset;

When the state gets updated:

useEffect(() => {
  window.scrollTo(0, scrollRef.current)
});

The Complete Code:

export default () => {
   const scrollRef = useRef(window.pageYOffset);
   ...
   scrollRef.current = window.pageYOffset;
   useEffect(() => {
      window.scrollTo(0, scrollRef.current)
   });

   return (
      ...
   );
}

On state update, I want to change back to the previous window position by not having this "shaky" behavior. (By shaky I mean it looks like he scrolls to the top and right after to the previous position so it looks like it shakes)

Share Improve this question edited Jul 29, 2019 at 13:48 Dennis Vash 54k12 gold badges117 silver badges132 bronze badges asked Jul 29, 2019 at 13:25 EmreEmre 1531 gold badge2 silver badges10 bronze badges 1
  • Try adding a sandbox – Dennis Vash Commented Jul 29, 2019 at 15:04
Add a ment  | 

2 Answers 2

Reset to default 1

The solution to your problem could look as follows:

sandbox

First create a custom usePrevious hook. This is just another function which uses the new useRef method to store the previous scroll value and only updates it when a new value is passed to it.

// 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;
}

In the actual ponent we declare a previousPosition variable. Every time the ponent re-renders, the our customHook is executed with the current position. It returns the previous position which then gets assigned.

Also with each render, the useEffect method is being executed, as we do not pass an Array as second argument. There we just pare the current scroll position with the previous and scroll back to the previous in case it changed.

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>
   );
}

If I understand correctly, use useLayoutEffect instead of useEffect. This will scroll back to the top before the ponent is rendered. Remember to add the dependency array.

发布评论

评论列表(0)

  1. 暂无评论