본문 바로가기
JavaScript

내 react-router-dom Link는 왜 작동하지 않는가?

by ma_ro 2020. 7. 4.

문제 발생

<Link to={isMovie ? `/movie/${item.id}` : `/show/${item.id}`}>

영화 앱을 만들던 중, 콘텐츠 아이디 값에 해당하는 URL을 찾아갈 수 있도록 링크를 걸었다. 그런데 링크는 제대로 걸려 있는 것 같은데, 링크를 눌러도 아무런 반응이 없었다. 확인해보니 URL은 제대로 변경이 되는데, 해당하는 URL로 렌더링이 되지 않는 것이었다.

 

잘 모를 땐 구글링을 해보자.

구글링을 해보니 이미 나같은 사람들이 꽤 많이 있었다!
그런데 문제는 원인이 다양해서, 딱 내 코드에 맞는 것을 찾기가 힘들다는 것이었다.
다만 대부분은 route의 세팅 문제였고, 어쨌든 내가 react-router-dom을 제대로 모르고 있다는 것은 사실인듯 했다.

 

그럼 내 문제는??

그러다 문득 든 생각.
주소가 변했다는 것을 인식을 못하는 건가??

내 Router는 이렇게 설정되어 있었다.

  <Router>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route path="/tv" component={TV} />
      <Route path="/search" component={Search} />
      <Route path="/movie/:id" component={Detail}/>
      <Route path="/show/:id" component={Detail}/>
    </Switch>
  </Router>

그럼 테스트를 해보자.
원래는 "/movie/5235" 이런 식으로 받는 것을 링크 주소를 바꿔 보았다.

"/search"의 경우, 작동이 잘된다.
"/show/5235"의 경우, 작동이 안된다.

주소 변경은 인식한다. 그런데 so what?
"/movie/:id"와 "/show/:id"는 같은 컴포넌트를 렌더링하고 있다. 이것을 같은 것으로 생각하기 때문에 렌더링의 필요성을 못 느끼는 것이다.
같은 건데 굳이 해야돼?? 이런 느낌.
결국 이게 다르다는 것을 Router에게 가르쳐줘야한다.
컴퓨터란 역시... 부지런하지만 멍청한 친구다.

 

그래서 어떻게 고쳐야 하는데??

원인을 알았으니 이제 제대로 구글링을 할 수 있다. (??!!)
그리고 그 결과, 컴포넌트에 key값을 주면 다르게 인식하게 할 수 있다는 것을 알게 되었다.

 

If you do need a component remount when route changes, you can pass a unique key to your component's key attribute (the key is associated with your path/route). So every time the route changes, the key will also change which triggers React component to unmount/remount. I got the idea from this answer

출처: https://stackoverflow.com/questions/32261441/component-does-not-remount-when-route-parameters-change

 

이런 방법이!
그럼 코드를 고쳐본다.

<Route path="/movie/:id" render={(props) => (
  <Detail key={props.match.params.id} {...props}/>
)}/>
<Route path="/show/:id" render={(props) => (
  <Detail key={props.match.params.id} {...props}/>
)}/>

 

작동이 잘된다. :)

그리고 좀 더 찾아보다가 놀라운 것을 발견했다.

 

If the same component is used as the child of multiple <Route>s at the same point in the component tree, React will see this as the same component instance and the component’s state will be preserved between route changes. If this isn’t desired, a unique key prop added to each route component will cause React to recreate the component instance when the route changes.

https://reactrouter.com/web/api/Route/route-render-methods

 

무려 공식 문서 Route 항목에 정확히 동일한 부분에 대해서 설명을 하고 있었다.
( 다시 한 번 느끼는 공식문서의 위엄 )
위의 스택오버플로 댓글을 보면 알겠지만, 답변에 대해 Brilliant!! 이러고 난리가 났다.

여기나 저기(?)나 사용설명서 안읽어보는 건 똑같은가보다.

 

그리고 공식문서를 좀 더 살펴보고 수정한 최종 route 설정.

<Router>
  <Switch>
{/* component, render, children 메서드를 사용하는 것은 hooks가 소개되기 전 버전을 위한 것으로 children elements를 사용한 방법이 더 권장된다. */}
    <Route exact path="/">
      <Home />
    </Route>
    <Route path="/tv">
      <TV />
    </Route>
    <Route path="/search">
     <Search />
    </Route>
    <Route path="/movie/:id" render={(props) => (
      <Detail key={props.match.params.id} {...props}/>
    )}/>
    <Route path="/show/:id" render={(props) => (
      <Detail key={props.match.params.id} {...props}/>
    )}/>
  </Switch>
</Router>

'JavaScript' 카테고리의 다른 글

Google api client 라이브러리 node-js 삽질기  (0) 2020.07.01
Webpack  (0) 2020.03.13
JavaScript - Typed Array  (0) 2020.03.11
MongoDB 파일 다루기  (0) 2020.03.08
MongoDB with node.js  (0) 2020.03.03

댓글