본문 바로가기
개발/React

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

by 피로물든딸기 2023. 12. 16.
반응형

리액트 전체 링크

 

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

 

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

 

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();
반응형

댓글