React Router가 v6으로 업데이트 되면서 꽤 많은 부분이 바뀌었다. 공식 문서에선 상세한 마이그레이션 가이드도 제공하고 있다. v6을 사용하려면 React 16.8 버전 이상 사용해야 한다. v6은 이전 버전 대비 번들 사이즈도 70% 이상 줄었다고 한다(패키지 업데이트만으로 번들 크기 최적화가 가능하다는 뜻).

Switch → Routes


<Switch> 컴포넌트가 <Routes>라는 이름으로 변경됐다. 바뀐 이름이 더 직관적인 것 같다. <Route>만 단독으로 사용할 수도 없게 됐다. <Route>를 사용하려면 항상 <Routes>로 감싸줘야 한다.

// v5
<Switch>
  <Route ... />
</Switch>

// v6
<Routes>
  <Route ... />
</Route>

exact 옵션 삭제

v6부터 경로가 정확히 일치하도록 매칭 규칙이 바꼈다. 더이상 exact 옵션을 명시하지 않아도 된다. 모든 라우트는 기본적으로 exact 옵션이 붙는다고 보면 된다. 하위 경로에 다른 라우트를 매칭시키고 싶을 때(서브 경로가 필요할 때) URL 뒤에 * 기호를 붙이면 된다.

// v5 (exact 옵션을 붙이기 않았기 때문에 /profiles/... 하위 경로가 매칭될 수 있다)
<Route path="/profiles" />

// v6
<Route path="/profiles/*" />

<Route> element 속성

v5에서 Route 컴포넌트를 렌더할 때 component render children 속성을 사용했다. v6 부턴 이 속성들이 모두 없어지고 element로 통일됐다. 더이상 inline function을 이용해 routeProps를 넘길 수도 없다. 대신 Router에서 제공하는 Hooks(useLocation 등)를 통해 라우트 객체에 접근할 수 있다.

// v5
<Route path="profiles" component={Profiles} />
<Route path="profiles" render={(routeProps) => <Profiles {...routeProps} />} />

// v6
<Route path="/profiles/*" element={<Profiles />} />

<Route> index 속성

Route에선 index 라는 props를 사용할 수 있다. indexpath=’/’ 와 동일한 의미를 가진다. 즉, 해당 라우트내에서 가장 상위 경로를 가리킨다고 보면 된다. 예를들면...

아래 예시에서 /courses 경로에 진입하면 첫번째 서브 라우트의 index/courses 경로와 동일하므로 CoursesIndex 컴포넌트를 렌더한다.

function Courses() {
	return (
		<div>
			<h2>Courses</h2>
			<Outlet /> {/* 경로에 따라 CoursesIndex 혹은 Course 컴포넌트 렌더 */}
		</div>
	)
}
// CoursesIndex / Course 컴포넌트 생략

const App = () => {
  return (
		<Routes>
      <Route path="/courses" element={<Courses />}>
        <Route index={true} element={<CoursesIndex />} />
        <Route path="/courses/:id" element={<Course />} />
      </Route>
    </Routes>
  );
};

export default App;