본문 바로가기
Frontend/- React router

React-router-dom : loader에 대해서

by 코딩쥐 2024. 9. 29.

React-router-dom의 loader는 페이지가 렌더링 되기 전에 데이터를 불러오고, 해당 데이터를 컴포넌트에서 사용할 수 있도록 하는 기능으로, <createBrowserRouter/>와 함께 사용할 수 있다. 

  • useLoaderData
    현재 컴포넌트와 연결된 로더 함수에서 반환된 데이터를 가져온다.
    • 1) 로더함수 연결
         createBrowserRouter([ {path: '경로', element: <컴포넌트/>, loader: 로더함수} ])
    • 2) 반환된 데이터 가져오기
          const 변수명 = useLoaderData();
  • useRouterLoaderData
    현재 렌더링된 모든 라우트의 로더 데이터를 사용할 수 있다. 이 훅은 컴포넌트가 중첩이 되어있을 경우 유용하게 사용된다. 사용시에 반드시 id값이 있어야 한다.
    • 1) 로더함수 연결
          createBrowserRouter([ {path: '경로', element: <컴포넌트/>, id: "아이디",loader: 로더함수} ])
    • 2) 반환된 데이터 가져오기
          const 변수명 = useRouteLoaderData("아이디")

 

loader 함수가 가지고 있는 매개변수는 다음과 같다. 

  • function 함수명({params, request})
    • params : 현재 라우트의 URL 파라미터를 포함하는 객체다. URL에서 정의한 가변인자와 매핑된다.
    • request : 웹 요청에 대한 모든 정보를 담고 있는 객체이다.

아래는 라우터를 { path: "/router/:postId", element: <Comp1 />, loader: myLoader }로 설정하고, url을 /router/1이라고 작성했을 때의 예제이다. 콘솔로 로더 함수의 매개변수를 확인해보면 params의 경우에는 /:postId를, request의 경우에는 웹 요청에 대한 모든 정보를 담고 있는 것을 볼 수 있다. 

 

useLoaderData 사용하기

loader를 통해 jsonplaceholder.typicode.com/posts에서 데이터를 받아 올 예정이다.

 

1. loader 함수 작성

postId를 가변인자로 받아 해당하는 postId의 데이터를 불러 올 예정이다. response가 제대로 불러와지지 않는다면 Error를 발생시키고, userRouterError 훅을 사용할 예정이다.

const myLoader = async ({ params, request }) => {
  const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.postId}`);
  if (!response.ok) {
    throw new Error;
  }
  return response.json();
};

 

2. 전체 라우터 설정

const router = createBrowserRouter([
  { path: "/router/:postId", element: <Comp1 />, errorElement: <ErrorPage/>, loader: myLoader }
]);

 

3. RouteProvider를 통해 라우터를 제공

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Comp1 from "./components/Comp1";
import ErrorPage from "./components/ErrorPage";

const myLoader = async ({ params, request }) => {
  const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.postId}`);
  if(!response.ok){
    throw new Error;
  }
  return response.json();
};

const router = createBrowserRouter([
  { path: "/router/:postId", element: <Comp1 />, errorElement: <ErrorPage/>, loader: myLoader }
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

 

4. useLoaderData를 통해 데이터 사용

해당하는 데이터에 들어있는 id, title, body를 가져와서 사용할 예정이다.

import {  useLoaderData } from "react-router-dom";

const Comp1 = () => {
    const data = useLoaderData();

    return (
        <div>
            <h2>{data.id}의 정보</h2>
            <h2>{data.title}</h2>
            <p>{data.body}</p>
        </div>
    );
}

export default Comp1;

 

 



useRouterLoaderData 사용하기

1. loader 함수 작성

loadHomeData는 <Home/> 컴포넌트와 연결 될 로더함수이고, loadRootData는 <Root/> 컴포넌트와 연결 될 로더함수이면서 부모 요소의 로더함수이다.

async function loadHomeData() {
  return { message: 'Home Data' }
}

async function loadRootData() {
  return { message: "Root data" }
}

async function loadAboutData() {

  const jsonData = await fetch("https://jsonplaceholder.typicode.com/posts/1");
  const data = jsonData.json();
  return data;
}

 

2. 전체 라우터 설정

const router = createBrowserRouter([
  {
    path: '/', element: <Root />,
 
    id: "root",
    loader: loadRootData,
    children: [
      {
        index: true, element: <Intro />
      },
      {
        path: 'home', element: <Home />,
        id: "home",
        loader: loadHomeData
      },
      {
        path: 'about', element: <About />,
        id: "about",
        loader: loadAboutData
      }
    ]
  },
]);

 

3. RouteProvider를 통해 라우터를 제공

function App() {
  return <RouterProvider router={router} />
}

export default App

 


4. useRouteLoaderData를 통해 데이터 사용

"root" 아이디를 가져와서 사용한다. 

import {useLoaderData, useRouteLoaderData} from 'react-router-dom'

const Home = () => {

    const data = useLoaderData();
    const rootdata = useRouteLoaderData("root");

    return(
        <div>
            <h2>Home</h2>
            <p>useLoaderData : {data.message}</p>
            <p>useRouteLoaderData : {rootdata.message}</p>
        </div>
    )
}

export default Home;

 

<<전체 코드 >> 

더보기
// App.jsx
import './App.css'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import Root from './pages/Root';
import Intro from './containers/Intro';
import Home from './containers/Home';
import About from './containers/About';


async function loadHomeData() {
  return { message: 'Home Data' }
}

async function loadRootData() {
  return { message: "Root data" }
}

async function loadAboutData() {

  const jsonData = await fetch("https://jsonplaceholder.typicode.com/posts/1");
  const data = jsonData.json();
  return data;
}


const router = createBrowserRouter([
  {
    path: '/', element: <Root />,
 
    id: "root",
    loader: loadRootData,
    children: [
      {
        index: true, element: <Intro />
      },
      {
        path: 'home', element: <Home />,
        id: "home",
        loader: loadHomeData
      },
      {
        path: 'about', element: <About />,
        id: "about",
        loader: loadAboutData
      }
    ]
  },
]);

function App() {
  return <RouterProvider router={router} />
}

export default App
// Root.jsx
import { Outlet } from "react-router-dom";
import Navigator from "../containers/Navigator";

const Root = () => {

    return (
        <div>
            <h1>Root</h1>
            <Outlet/>
            <Navigator />
        </div>
    )
}

export default Root;
// Intro.jsx
const Intro = () => {

    return(
        <div>
            <h2>Intro</h2>
            <p>첫 페이지 입니다. 아래 버튼을 눌러주세요.</p>
        </div>
    )
}

export default Intro;
//Home.jsx
import {useLoaderData, useRouteLoaderData} from 'react-router-dom'

const Home = () => {

    const data = useLoaderData();
    const rootdata = useRouteLoaderData("root");

    return(
        <div>
            <h2>Home</h2>
            <p>useLoaderData : {data.message}</p>
            <p>useRouteLoaderData : {rootdata.message}</p>
        </div>
    )
}

export default Home;
// About.jsx
import { useLoaderData } from "react-router-dom";

const About = () => {

    const data = useLoaderData();

    return (
        <div>
            <h2>About</h2>
            <p>id : {data.id}</p>
            <p>title : {data.title}</p>
        </div>
    )
}

export default About;
// Navigator.jsx
import { Link } from "react-router-dom"
import styles from "./Navigator.module.css"

const Navigator = () => {
    return (
        <div>
            <Link to="home" className={styles.button}>Home</Link>
            <Link to="about" className={styles.button}>About</Link>
        </div>
    )
}
export default Navigator;