개발/React

리액트 - useLocation으로 페이지 이동시 스크롤 상단으로 초기화하기 (Scroll to Top on Page Transition)

피로물든딸기 2023. 12. 16. 00:15
반응형

리액트 전체 링크

 

리액트에서 페이지를 이동할 때, 스크롤을 상단으로 옮겨보자.

 

테스트를 위해 아래와 같은 라우터를 만든다.

 

Scroll1.js는 다음과 같다. (Scroll2는 Component의 이름만 다르다.)

import React from "react";

const Scroll1 = () => {
  const numbers = Array.from({ length: 100 }, (_, index) => index + 1);

  return (
    <div>
      {numbers.map((number) => (
        <p key={number}> Scroll 1 : {number}</p>
      ))}
    </div>
  );
};

export default Scroll1;

 

스크롤이 만들어지도록 <p> 태그를 100개 생성하였다.

 

Scroll1에서 Scroll2로 번갈아가며 움직여보자.

 

위의 결과대로 스크롤이 원래대로 고정된 것을 알 수 있다.


구현

 

useLocation을 이용해서 스크롤을 처음으로 초기화할 수 있다.

InitScrollTop이 실제로 렌더링 될 필요는 없으므로, null을 리턴한다.

import React, { useEffect } from "react";
import { useLocation } from "react-router-dom";

const InitScrollTop = () => {
  const { pathname } = useLocation();
  
  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
};

export default InitScrollTop;

 

그리고 InitScrollTop index.js에 추가한다.

import InitScrollTop from './InitScrollTop';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter basename={process.env.PUBLIC_URL}>
    <InitScrollTop />
    <App />
  </BrowserRouter>
);

 

이제 링크를 변경하면 스크롤이 상단으로 위치하는 것을 알 수 있다.


전체 코드는 다음과 같다.

 

Scroll1.js

import React from "react";

const Scroll1 = () => {
  const numbers = Array.from({ length: 100 }, (_, index) => index + 1);

  return (
    <div>
      {numbers.map((number) => (
        <p key={number}> Scroll 1 : {number}</p>
      ))}
    </div>
  );
};

export default Scroll1;

 

Scroll2.js

import React from "react";

const Scroll2 = () => {
  const numbers = Array.from({ length: 100 }, (_, index) => index + 1);

  return (
    <div>
      {numbers.map((number) => (
        <p key={number}> Scroll 2 : {number}</p>
      ))}
    </div>
  );
};

export default Scroll2;

 

App.js

import React from "react";
import { Route, Link, Routes } from "react-router-dom";

import "./App.css";

import Scroll1 from "./page/Scroll1.js";
import Scroll2 from "./page/Scroll2.js";

const App = () => {
  return (
    <div className="App">
      <div>
        <Routes>
          <Route path="/scroll1" element={<Scroll1 />} />
          <Route path="/scroll2" element={<Scroll2 />} />
        </Routes>
      </div>
      <div className="router"> 
        <span>
          <Link to="/scroll1">Scroll 1</Link>
        </span>    
        <span>
          <Link to="/scroll2">Scroll 2</Link>
        </span>
      </div>
    </div>
  );
};

export default App;

 

InitScrollTop.js

import React, { useEffect } from "react";
import { useLocation } from "react-router-dom";

const InitScrollTop = () => {
  const { pathname } = useLocation();
  
  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
};

export default InitScrollTop;

 

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
import InitScrollTop from './InitScrollTop';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter basename={process.env.PUBLIC_URL}>
    <InitScrollTop />
    <App />
  </BrowserRouter>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
반응형