React.js 라우트 사용법

박경찬·2023년 4월 23일
0

이번 프로젝트에선 라우트를 v6를 사용하면서 기록을 하기 위해 남긴다.

v6에서는 BrowserRouter를 사용하지 않고 createBrowserRouter를 사용한다.

createBrowserRouter를 사용하면서 javaScript Objcet로 사용할수 있다.

path:"/"
를 작성해서 유저가 방문하는 위치가 URL 과 일치한다면 Rrouter는 URL과 일치하는 요소를 렌더링 한다.
const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
  },
]);

여기서 더이상 이제 index.tsx에서는 App을 렌더링 할필요가 없어진다.

  <React.StrictMode>
     <RouterProvider router={router} />
   //없어짐 <App />
  </React.StrictMode>
path:"/"
위 path는 "부모" 라고 생각해야한다. 그리고 뒤에 생성되는 components 들은 자식이라고 생각하면된다.

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      {
        path: "screen",
        element: <Screen />,
      },
    ],
  },
]);
"/"
Url 그 자체다 /Screen은 일종의 "/" 자식인셈이다.

여기서 이제 거의 다된거 같지만 실제로 /Screen 으로 이동하게 되면 브라우저는 아무런 반응 해주지 않는다

App의 자식을 render하길 원한다고 직접 전달해줘야한다.
이유는 아직 "/" 안에 있고 그안에 Screen을 포함하고 있기 때문이다.

function App() {
  return (
    <div>
      <Outlet />
    </div>
  );
}

Outlet이라는 컴포넌트를 통해 유저가 Screen페이지로 가면 reactRouter가 App를 보고 Outlet을 Screen으로 대체해달라! 요구 하면되는거다.

reactRouterV6의 장점으로는 에러를 컨트롤할수 있다는 점인데 매우 간단하고 직관적이다.

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      {
        path: "screen",
        element: <Screen />,
      },
    ],

    errorElement: <NotFound />,
  },
]);
NotFound
컴포넌트가 페이지를 찾지 못했을때 404라고 가정하면 errorElement를 사용하여 컨트롤 할수 있다. 자식을 발견하지 못하거나 컴포넌트들이 충돌할때도 사용할수 있다.
const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      {
        path: "screen",
        element: <Screen />,
        errorElement: <ErrorComponent />,
      },
    ],

    errorElement: <NotFound />,
  },
]);

errorElement를 사용하지 않으면 사용하는 앱이 죽어버리기 때문에 사용하는걸 권장한다.

useNavigate는 유저를 이동시키거나 유저가 이동하고 싶은 곳으로 갈수있게 도와준다.

	<header>
    	<ul>
          <li>
            <Link to={"/"}>Home</Link>
          </li>
          <li>
            <Link to={"/screen"}>screen</Link>
          </li>
      	</ul>  
    </header>

useNavigate 사용

const navigate = useNavaigate();
	const onScreenClick = () => {
      navigate("/screen")
    }

  return(
      <header>
          <ul>
            <li>
              <Link to={"/"}>Home</Link>
            </li>
            <li>
              <button onClick={onScreenClick}>screen</button>
            </li>
          </ul>  
      </header>
  )

useParam

	
const users =[
  
  {
  	id:1,
    name:"a"
  },
   {
  	id:2,
    name:"b"
  }

]

user의 가상의 데이터가 있다고 가장하고 이유저의 대해 상세정보를 보고 싶거나 상세정보를 보기위한 component를 보고싶다면 useParam을 사용한다.

return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map((el) => (
          <li key={el.id}>
            <Link to={`/users/${el.id}`}>{el.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );

실제로 URL의 parameter로 유저를 보낼수 있다. 실제로 이동하면 NotFound컴포넌트가 보여지면서 페이지는 원하는 곳으로 갈수 없다.

router 컴포넌트에 users/라는 페이지에서 내가 선택한 유저의 상세정보를 볼수있게 작성해야한다. URL이 parameter를 가졌으니 알려준다고 보면된다.

router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      {
        path: "about",
        element: <Screen />,
        errorElement: <ErrorComponent />,
      },
			//추가된부분
      {
        path: "users/:userId",
        element: <User />,
      },
    ],

    errorElement: <NotFound />,
  },
]);

여기까지 3가지에 매칭되는데 "/" 매칭되니까 App를 rander되고
Outlet을 rander할테고 그다음 users를 찾게 되고 userId가 있다는걸 알게되 그러면 여기서userId가 뭔지 알려주면 끝이다.

	const {userId} = useParams();
	return <h1>User {userId}의 이름은							  		{users[Number(userId)-1].name}
		  </h1>

useParams에는 원하는걸 넣어주면되는데 현재 지금 내가 필요한건 userId가 필요하다.

만약 users만 있는 페이지를 보여주고싶다면??

router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      {
        path: "about",
        element: <Screen />,
        errorElement: <ErrorComponent />,
      },

      {
        path: "users",
        element:<UserHome/>,
        children :[{
                path:"userId",
                element:<User/>
        }]
       
      },
    ],

    errorElement: <NotFound />,
  },
]);

위코드로 하면 페이지를 찾을수 없다고 나오는데.. 이유를 모르겠따..

이동하는 div 태그에도 파라미터값을 받아서 링크로 이동할수 있게끔 했는데.. 왜 안될까..

결국엔 자식으로 두지 않았다..
후..이유를 찾지 못했는데 공식문서를 좀 다시 들여다봐야겠다..


router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      {
        path: "about",
        element: <Screen />,
        errorElement: <ErrorComponent />,
      },

      {
        path: "users",
        element:<UserHome/>,
        errorElement: <ErrorComponent/>
       
      },
      {
        path: "user/:userId",
        element:<UserHome/>,
        errorElement: <ErrorComponent/>

      },
    ],

    errorElement: <NotFound />,
  },
]);

마지막으로 정말 신박한 기능!! 페이지로 넘어갈떄 이떄 props나 import를 통해서 자식이게 데이터를 전달했는데 새로 업데이트된 라우터에서는 RouterContext로 자식에게 데이터를 전달할수 있다.


 <div>
      <h1>
        {userId}의 이름은 {users[Number(userId) - 1].name}
      </h1>
      <Link to="follower">Follower</Link>
      <Outlet context={{ name: "chan" }} />
</div>
context를 사용해서 부모컴포넌트에서 자식에게 원하는 데이터를 넘겨줄수있다.

자식컴포넌트에서 데이터를 받아주기만 하면된다.


export default function Follower() {
  const ctx = useOutletContext();
  return <div>Follower</div>;
}

0개의 댓글