React Router v4 - Keep scrolling position when switching compone

ghz 6months ago ⋅ 296 views

React Router v4 - Keep scrolling position when switching components

I have two <Route>s created with react-router.

  • /cards -> List of cards game
  • /cards/1 -> Detail of card game #1

When the user clicks on the "Return to list", I want to scroll the user where he was on the list.

How can I do this?

Answers

To scroll the user back to their previous position in the list of cards when they navigate back from a card detail page (/cards/1) to the list page (/cards), you can use the scrollTo method provided by the browser's window object in combination with React Router's useLocation and useRef hooks.

Here’s a step-by-step approach to achieve this:

Step-by-Step Implementation

1. Setup Scroll Restoration

React Router v5 and later provide a useLocation hook that allows you to get the current location object. You can use this along with useRef to store and restore the scroll position.

// ListCards.js

import React, { useEffect, useRef } from 'react';
import { Link, useLocation } from 'react-router-dom';

const ListCards = () => {
  const location = useLocation();
  const scrollRef = useRef(null);

  useEffect(() => {
    if (scrollRef.current) {
      window.scrollTo(0, scrollRef.current.offsetTop);
    }
  }, [location.key]);

  return (
    <div>
      {/* List of cards */}
      <ul>
        <li>
          <Link to="/cards/1">Card #1</Link>
        </li>
        <li>
          <Link to="/cards/2">Card #2</Link>
        </li>
        {/* Add more cards as needed */}
      </ul>

      {/* Store current scroll position */}
      <div ref={scrollRef} />

      {/* Additional content */}
    </div>
  );
};

export default ListCards;

2. Explanation

  • useLocation Hook: This hook from React Router provides access to the current location object. We use it to detect when the user navigates between different routes.

  • useRef Hook: This hook creates a mutable ref object (scrollRef) which can store a reference to a DOM element. In this case, it's used to create a placeholder div (<div ref={scrollRef} />) where we store the scroll position.

  • useEffect Hook: This hook runs after every render and is used to scroll the window to the position stored in scrollRef.current.offsetTop. This ensures that when the user navigates back to the list (/cards), they are scrolled to the previous position in the list.

  • Links to Detail Pages: These are represented by <Link> components that navigate to specific card detail pages (/cards/1, /cards/2, etc.).

3. Implementing Card Detail Page

On the card detail page (/cards/1, /cards/2, etc.), ensure you also have a link back to the list of cards. When the user clicks "Return to list", it should preserve the scroll position automatically.

// CardDetail.js

import React from 'react';
import { Link } from 'react-router-dom';

const CardDetail = ({ match }) => {
  const { id } = match.params;

  return (
    <div>
      <h2>Card Detail #{id}</h2>
      {/* Detail content */}
      <Link to="/cards">Return to list</Link>
    </div>
  );
};

export default CardDetail;

Summary

By using useLocation to detect route changes and useRef to store and restore scroll positions, you can effectively implement scroll restoration in your React application when navigating between list and detail pages. This approach ensures a smooth user experience where users are returned to their previous position in the list after viewing details of a card. Adjust the components and routes as needed based on your specific application structure and requirements.