Trouble Shooting

[React] 중첩 라우팅 시 정상적으로 렌더링되지 않아 빈 화면이 뜰 때 (+Outlet)

깨구르르 2024. 11. 15. 23:55
728x90

1. 문제점

localhost:3000/users/sign_in 경로로 접속을 시도했을 때,

'로그인 페이지입니다.'라는 문구가 나오지 않고,

빈 화면이 떴다.

 


 

2. 기존 코드

//App.js
import logo from './logo.svg';
import './App.css';
import { Desktop, Mobile, Tablet } from './layouts/ResponsiveComponent';
import { RouterProvider } from 'react-router-dom';
import root from './router/root';

function App() {
  return (
    <>
      <Desktop>
        <RouterProvider router={root} />
      </Desktop>
      <Tablet>
        <RouterProvider router={root} />
      </Tablet>
      <Mobile>
        <RouterProvider router={root} />
      </Mobile>
    </>
  );
}

export default App;

App.js를 위와 같이 작성해서 root.jsx 설정을 애플리케이션 전체에 적용하게 했다.

 

// root.jsx
import { lazy, Suspense } from "react";
import { createBrowserRouter } from "react-router-dom";
import user_router from "./user_router";

const Loading = <div>Loading...</div>;

const Main = lazy(() => import("../pages/main/Mainpage"));

const root = createBrowserRouter([
    {
        path: "/",
        element: <Suspense fallback={Loading}><Main/></Suspense>
    },
    {
        path: "/users",
        element: <Suspense fallback={Loading}></Suspense>,
        children: user_router()
    }
]);

export default root;

localhost:3000을 입력하면 Mainpage가 뜨도록,

localhost:3000/users를 입력하면 아무것도 안 뜨도록 위와 같이 설정하였다. (이게 문제였다.)

또한 url이 users/sign_in, users/sign_up 등과 같은 형태를 띨 때는 user_router와 연결되게 하였다.

 

// user_router.jsx
import { lazy, Suspense } from "react";

const Loading = <div>Loading...</div>;
const Sign_in = lazy(() => import("../pages/users/Sign_in_page"));

const user_router = () => {
    return [
        {
            path: "sign_in",
            element: <Suspense fallback={Loading}><Sign_in/></Suspense>
        }
    ];
};

export default user_router;

user_router에서는 Sign_in_page가 부모의 경로 + sign_in이라는 경로로 연결될 수 있게 하였다.

 

// Sign_in_page.jsx
const Sign_in = () => {

    return (
        <>
            로그인 페이지입니다.
            ghdod
        </>
    )
}

export default Sign_in;

Sign_in_page 코드는 위와 같다.

 


 

3. 원인

user_router() 함수가 children 배열을 반환하도록 작성되어 있지만,

이를 포함하는 부모 라우트(path: "/users" 경로에 해당)는 element가 비어있는 fragment로 작성되었기 때문이다.

따라서 localhost:3000/users/sign_in으로 접근하면, 해당 경로에 해당하는 element가 없어서 빈 화면이 나타난 것이다.

 


 

4. 해결방법

부모 경로("/users" 경로)에 Outlet을 추가하였다.

react-router-dom의 Outlet 컴포넌트는 부모 라우트가 중첩된 자식 경로를 렌더링하는 역할을 한다.

// root.jsx
import { lazy, Suspense } from "react";
import { createBrowserRouter } from "react-router-dom";
import user_router from "./user_router";

const Loading = <div>Loading...</div>;

const Main = lazy(() => import("../pages/main/Mainpage"));

const root = createBrowserRouter([
    {
        path: "/",
        element: <Suspense fallback={Loading}><Main/></Suspense>
    },
    {
        path: "/users",
        element: <Outlet/>,
        children: user_router()
    }
]);

export default root;

위와 같이 코드를 수정했더니 localhost:3000/users/sign_in을 주소창을 입력했을 때 로그인 페이지가 잘 뜬다!

 

왜 Outlet이 필요할까?

  • 부모 라우트는 자식 라우트를 렌더링할 영역을 제공해야 함
  • Outlet 컴포넌트는 부모 라우트의 JSX 내에서 자식 라우트의 내용을 출력하는 역할을 함
  • 만약 Outlet이 없다면, 부모 라우트는 자식 라우트를 어디에 렌더링할지 알 수 없기 때문에, 자식 경로가 존재해도 화면에 아무것도 표시되지 않음

 

728x90