์ฃผ์ด์ง ํฌ์ผ๋ชฌ ์ค์์ ์ํ๋ ํฌ์ผ๋ชฌ์ ์ถ๊ฐํ ์ ์๋ ํ๋ก์ ํธ๋ฅผ ์งํํ๊ณ ์๋ค.
ํฌ์ผ๋ชฌ์ ์ด 6๊ฐ๋ฅผ ์ ํํ ์ ์๊ณ ํฌ์ผ๋ชฌ 3๊ฐ๋ฅผ ์ ํํ์ผ๋ฉด 3๊ฐ์ ํฌ์ผ๋ชฌ์ด ๋ณด์ด๊ณ ์ ํํ์ง ์์ 3๊ฐ๋ ๊ธฐ๋ณธ ์ด๋ฏธ์ง๊ฐ ๋ณด์ฌ์ผ ํ๋ค.
์ ํํ 3๊ฐ์ ์ ํํ์ง ์์ ๊ธฐ๋ณธ ์ด๋ฏธ์ง๊ฐ ํ ๋ฒ์ ๋ ๋๋ง์ด ์ด๋ฃจ์ด์ ธ์ผ ํ๋๋ฐ, ์ด ๋ ๋๋ง ๋ฐฉ์์ ์ด๋ป๊ฒ ํด์ฃผ์ด์ผ ํ ์ง ๊ณ ๋ฏผํ ๊ฒ์ ์ ๋ฆฌํด ๋ณด๋ ค๊ณ ํ๋ค.
์ฒ์ ์ ๊ทผ ๋ฐฉ์๊ณผ ์ด์
์ฒ์ ์๊ฐํ ๋ฐฉ์์ useState ์ด๊ธฐํ๋ฅผ ํฌ๊ธฐ๊ฐ 6์ธ ๋ฐฐ์ด๋ก ๋ง๋ค์ด๋ฒ๋ฆฌ๊ธฐ
์๋์ ๊ฐ์ด ๊ฐ๊ฐ์ ์์๋ฅผ null ๋ก ์ด๊ธฐํํ ํฌ๊ธฐ๊ฐ 6์ธ ๋ฐฐ์ด์ useState ๋ก ์ค์ ํ์๋ค. (๋น์์ ์ด๊ฒ ์ต์ ์ด๋ผ๊ณ ์๊ฐํจ)
ํ์ง๋ง ์ด๋ ๊ฒ ํด๋ฒ๋ฆฌ๋๊น ์ฌ์ํ ๋ฌธ์ ์ ๋ค์ด ๋ฐ์ํ๊ธฐ ์์ํ๋ค. ๐
const [selectedPokemon, setSelectedPokemon] = useState(Array(6).fill(null));
1. add ๋ฉ์๋์ ๋ณต์ก์ฑ
์๋ ์ฝ๋๋ seletedPokemon ์ ๋ฐ์ดํฐ ํ ๊ฐ๋ฅผ ์ถ๊ฐํ๋ ํจ์์ด๋ค.
const addPokemon = (newPokemon) => {
setSelectedPokemon((prev) => {
const emptyIndex = prev.findIndex((pokemon) => pokemon === null);
if (emptyIndex !== -1) {
const updatePokemon = [...prev];
updatePokemon[emptyIndex] = newPokemon;
return updatePokemon;
}
return prev;
});
};
๋จ์ํ ๋ฐ์ดํฐ ํ ๊ฐ๋ฅผ ์ถ๊ฐํ๋ ๋ก์ง๋ง ์์ด๋ ๋๋๋ฐ, ๋ฐฐ์ด์์ null ์ธ ์์๋ฅผ ์ฐพ๊ณ ... ๋ง์ฝ null ์ธ ์์์ ์ธ๋ฑ์ค๋ฅผ ์ฐพ์์ผ๋ฉด.. ๊ทธ ์ธ๋ฑ์ค์ newPokemon ์ ๋ฃ์ด์ฃผ๊ณ ์๋ค. ๋ญ๊ฐ ๋ณต์กํ๋ค.
๋ฌผ๋ก ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ์ถ๊ฐ ๊ธฐ๋ฅ ๋ก์ง์ ์ถฉ๋ถํ ๋ณต์กํด์ง ์ ์๋ค. ํ์ง๋ง ํ์ฌ ํ์ํ ๊ธฐ๋ฅ์ ์ด๋ ์กฐ๊ฑด ์์ด ๊ทธ๋ฅ '์ถ๊ฐ' ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ทธ ๋ฐ์ดํฐ๊ฐ state ์ ์ถ๊ฐํ๋ ๊ธฐ๋ฅ์ผ ๋ฟ์ด๋ค.
2. ์ ๊ฑฐํ ๋ null ์ค๋ฅ
์๋ ์ฝ๋๋ ์ญ์ ํจ์์ด๋ค.
const removePokemon = (pokemon) => {
const updatePokemon = selectedPokemon.filter((p) => {
return p.id !== pokemon.id;
});
setSelectedPokemon(updatePokemon);
};
์ญ์ ํ๋ ค๋ ๋ฐ์ดํฐ์ id ์ ๋ค๋ฅธ ๊ฒ๋ค์ ํํฐํ๊ณ ํํฐ ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ set ํ๋ ๋ฐฉ์์ด๋ค. ์ด ๊ธฐ๋ฅ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
์๋๋ ์ค๋ฅ ๋ฉ์์ง์ด๋ค.
Dex.jsx:42 Uncaught TypeError: Cannot read properties of null (reading 'id')
at Dex.jsx:42:16
at Array.filter (<anonymous>)
at removePokemon (Dex.jsx:41:43)
at onClick (PokemonCard.jsx:22:13)
at HTMLUnknownElement.callCallback2 (chunk-M324AGAM.js?v=a49fcf27:3672:22)
at Object.invokeGuardedCallbackDev (chunk-M324AGAM.js?v=a49fcf27:3697:24)
at invokeGuardedCallback (chunk-M324AGAM.js?v=a49fcf27:3731:39)
at invokeGuardedCallbackAndCatchFirstError (chunk-M324AGAM.js?v=a49fcf27:3734:33)
at executeDispatch (chunk-M324AGAM.js?v=a49fcf27:7012:11)
at processDispatchQueueItemsInOrder (chunk-M324AGAM.js?v=a49fcf27:7032:15)
ํฌ์ผ๋ชฌ์ ํ ๊ฐ๋ผ๋ ์ ํํ์ง ์์ ์ํ์ด๋ฉด selectedPokemon ๋ฐฐ์ด์ ์ํํ ๋ null ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ๋ฌผ๋ก null ์ผ ๊ฒฝ์ฐ ์ด์ฐ์ ์ฐํด์ ์ค๋ฅ๊ฐ ๋์ง ์๋๋ก ํ ์ ์๊ฒ ์ง๋ง ๋ญ๊ฐ ๋ณต์กํ๊ณ ๋ง์ ์ ๋ ๋ค.
์์ ํ ๋ฐฉ์
... ๊ณ ๋ฏผ๋์ ๋ฐฉ๋ฒ์ ๋ฐ๊ฟ ์ ์์๋ค. ์์ ํ ๋ฐฉ์์ PokemonList ์ PokemonCard ์์ ๋ถ๊ธฐ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด๋ค.
์ฐ์ ๋ฌธ์ ์ ์์์ ์ธ useState ์ด๊ธฐํ ๋ฐฉ์์ ๋ณ๊ฒฝํ์๋ค.
const [selectedPokemon, setSelectedPokemon] = useState([]);
๋ฆฌ์คํธ ์ถ๋ ฅ์ ์ ํํ ํฌ์ผ๋ชฌ ๋ฐ๋ก ์ ํํ์ง ์์ ํฌ์ผ๋ชฌ ๋ฐ๋ก ๋ ๋๋ง ๋๋๋ก ํ๊ณ ์ ํํ์ง ์์ ํฌ์ผ๋ชฌ์ ๊ธธ์ด๋ฅผ 6์ผ๋ก ์ ํด๋๊ณ ์ ํํ ํฌ์ผ๋ชฌ์ ๊ฐ์๋ฅผ ๋บ ๊ฐ์๋ฅผ ๋ ๋๋งํ๋๋ก ํ๋ค.
return (
<StyledSection>
<h1>๋๋ง์ ํฌ์ผ๋ชฌ</h1>
<StyledDiv>
{selectedPokemon.map((pokemon) => {
return (
<PokemonCard
key={pokemon.id}
pokemon={pokemon}
removePokemon={removePokemon}
isSelected={true}
/>
);
})}
{Array.from({ length: 6 - selectedPokemon.length }).map((_, index) => (
<PokemonCard key={index} />
))}
</StyledDiv>
</StyledSection>
);
ํฌ์ผ๋ชฌ ์นด๋๋ ๋ถ๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ๋ค. props ๋ก ์ ๋ฌ๋ฐ์ pokemon ์ด ์์ผ๋ฉด ์ ํํ ํฌ์ผ๋ชฌ ์นด๋๊ฐ ๋ ๋๋ง๋๊ณ , pokemon ์ด ์ ๋ฌ๋์ง ์์์ผ๋ฉด ์ ํํ์ง ์์ ์นด๋๊ฐ ๋ ๋๋ง ๋๋๋ก ํ๋ค.
return pokemon ? (
<StyledDiv
onClick={() => {
navigate(DETAIL_URL + "/" + pokemon.id);
}}
>
<img src={pokemon.img_url} />
<span>{pokemon.korean_name}</span>
<span>No.{pokemon.id}</span>
{isSelected ? (
<button
onClick={(e) => {
e.stopPropagation();
removePokemon(pokemon);
}}
>
{"์ญ์ "}
</button>
) : (
<button
onClick={(e) => {
e.stopPropagation();
addPokemon(pokemon);
}}
>
{"์ถ๊ฐ"}
</button>
)}
</StyledDiv>
) : (
"์์"
);
๋ณ๊ฒฝํ ๋ฐฉ์์ด ์ต์ ์ ์๋์ง๋ผ๋.. ์ด์ ๋ณด๋ค ๊น๋ํด์ง ๋๋์ด๋ค.