// Dex
return (
<DexCss>
<h1>
Pick <span>Your</span> Pokemon !
</h1>
<Dashboard
selectedPokemons={selectedPokemons}
removePokemon={removePokemon}
/>
<PokemonList pokemonData={MOCK_DATA} addPokemon={addPokemon} />
<PokemonDetail pokemonData={MOCK_DATA} /> // 문제의 코드
</DexCss>
);
context
로 전역 상태 관리를 해 주면서, Detail component
도 전역으로 관리해줄 수는 없을까? 라는 생각에 Dex
파일에서 PokemonDetail
파일을 함께 export
해보았다.
그러자 디테일 화면이 렌더링되지 않는 문제가 발생했다. 원인이 뭘까?
Detail
파일을 Dex
에서 내려주지 않고, Router Component
에서 export
를 해주면 제대로 동작한다.
// Dex
return (
<DexCss>
<h1>
Pick <span>Your</span> Pokemon !
</h1>
<Dashboard
selectedPokemons={selectedPokemons}
removePokemon={removePokemon}
/>
<PokemonList pokemonData={MOCK_DATA} addPokemon={addPokemon} />
// PokemonDetail Component 삭제
</DexCss>
);
};
// Router
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dex" element={<Dex />} />
<Route path="/detail/:id" element={<PokemonDetail />} /> // Detail
</Routes>
</BrowserRouter>
);
};
PokemonDetail
이 렌더링되지 않은 이유는 Dex Component
에서 PokemonDetail
을 항상 렌더링하고 있기 때문이었다.
<PokemonDetail pokemonData={MOCK_DATA} /> // 문제의 코드
PokemonDetail
은 특정 포켓몬 카드를 클릭했을 때만 보여야 하고, URL에 id가 포함되어 있어야 올바르게 동작하는데 Dex 파일에서 작성하여 무조건 렌더링이 되는 상태로, URL
이 /dex/:id
형식이 아닐 때도 무조건 표시하려고 한다.
하지만 useParams()
를 사용할 수 없는 상황에서 실행되므로 id
값을 찾을 수 없기 때문에 오류가 뜨는 것이다. 또, 그 과정에서
const detailPokemon = MOCK_DATA.find((pokemon) => pokemon.id === Number(id));
이 코드로 id
값을 찾아오는데, find()
에서 값을 찾지 못해 undefined
를 반환할 수도 있다. 그런 경우 백지 화면이 발생할 수도 있다.
PokemonDetail
을 Dex.jsx
에서 직접 렌더링하지 않고, /dex/:id
에서만 렌더링되도록 설정하고, react-router-dom
의 Route
를 이용해 별도의 페이지로 이동하도록 만들어서 해결!
이로써 왜 Detail component
와 같은 모달 창, 기타 유사한 동작 원리를 가진 파일을 어떻게 라우팅해야 하는 지 알게 되었다. 컴포넌트 간의 구조를 짜는 데 많이 도움이 될 것 같다!