[React-router-dom] render와 component의 차이

기존 React Router에서 Route를 지정할 때, <Switch> 안에 <Route> 컴포넌트에서 path props으로 url을 지정하고 component props로 랜더링을 원하는 페이지 컴포넌트를 지정하였었다.

// Route.tsx

<Switch>
    <Route path='/add' component={AddPage}/>
    <Route path='/:id/edit' component={EditPage}/>
</Switch>

 

한 페이지 안에 3개의 UX 뎁스로 구성되어있는 UI에서 3번째 뎁스 까지 도달했을 때, Add 혹은 EditPage로 넘어가게 하였다. 2번째 뎁스에서 id값을 props로 넘기는 것을 받아왔을 때, focus가 해당 페이지를 벗어나면 AddPage 혹은 EditPage가 언마운트되었디가 다시 마운트되면서 3번째 뎁스 안의 title, content등의 state가 모두 초기화되어 작성한 내용이 빈칸으로 되는 이슈가 발생하였다.

구성하던 페이지 뎁스를 도식화해보았다.

해당 이슈가 발생한 원인은 한 페이지 안에 여러 개로 뎁스가 나뉘어 있는데 단일 페이지에 한 뎁스만을 가지고 있는 상황과 동일하게 작업해서 Route에 준 component props 때문이었다. component를 사용하면 router가 React.createElement를 사용해서 주어진 컴포넌트(Add/EditPage)에 대해 새로운 리액트 element를 생성하기 때문에 매번 랜더링 될 때마다 3번째 뎁스에 있는 페이지가 마운트와 언마운트가 반복되었다. 한 페이지 안에 여러 개의 뎁스를 사용하는 inline rendering을 쓰려면 render나 children props를 쓰라고 공식 문서에 나와있다(!) render의 경우, 매번 리액트 element를 새로 만들지 않아서 이전 뎁스에서 값을 props로 전달할 수 있다. render props 또한 component props와 마찬가지로 match, location, history와 같은 route props를 모두 사용할 수 있다.

 

 

Declarative routing for React apps at any scale | React Router

Version 6 of React Router is here! React Router v6 takes the best features from v3, v5, and its sister project, Reach Router, in our smallest and most powerful package yet.

reactrouter.com

 

기존에 Route.tsx에서 <Route/> 에 component props 주었던 것을 render props로 변경해서 언마운트되고 마운트되는 것을 방지하였다.

// Route.tsx

<Switch>
    <Route path='/add' render={() => (AddPage)}/>
    <Route path='/:id/edit' render={() => (EditPage)}/>
</Switch>