addPokemon: (state, action) => {
const pokemon = action.payload;
if (state.selectPokemon.some((p) => p.id === pokemon.id)) {
Swal.fire({
text: "같은 포켓몬은 중복으로 등록할 수 없습니다!",
icon: "warning",
});
} else if (state.selectPokemon.length >= 6) {
Swal.fire({
text: "더 이상 포켓몬을 등록할 수 없습니다!",
icon: "error",
});
} else if (pokemon.fromDetail) {
state.selectPokemon.push(pokemon);
localStorage.setItem(
"selectPokemon",
JSON.stringify(state.selectPokemon)
);
Swal.fire({
text: "포켓몬이 성공적으로 추가되었습니다!",
icon: "success",
});
} else {
state.selectPokemon.push(pokemon);
localStorage.setItem(
"selectPokemon",
JSON.stringify(state.selectPokemon)
);
}
}
Dex 페이지 내에 있는 리스트에서 추가 버튼을 누를 경우 카드의 css가 변경되어 추가되었음을 확인할 수 있는 반면, 디테일 페이지에서 추가를 눌렀을 때에는 뒤로가기를 하지 않으면 확인할 방법이 없어 디테일 페이지에서만 alert을 띄우고자 했다.
const handleAdd = () => { const addFrom = { ...detailPokemon, fromDetail: true }; dispatch(addPokemon(addFrom)); };그래서 detail 페이지 내에서 추가 버튼을 누르면 기존의 포켓몬 정보에 fromDetail: true 값이 추가된 객체가 넘어가도록 하고, 중복·최대 개수 확인 등의 조건문 뒤에 fromDetail 조건을 걸어 디테일 페이지에서 추가를 눌렀을 경우 alert을 띄우는 것으로 해결했다.
리덕스 툴킷으로 리팩토링 하기 전에는 삼항연산자 여러개와 쉼표 연산자(단일 표현식을 요구하는 곳에서 여러개의 표현식을 사용하고 싶을 때 사용)로 alert과 함께 불리언을 반환하는 로직을 사용했다.
그런데 리덕스 툴킷으로 리팩토링 하면서 ture, false값이 제대로 넘어오지 않아 해당 기능이 작동하지 않았다. 튜터님의 도움을 받아 식을 if문으로 변경하고 디테일 페이지에서 fromDetail을 넘겨주는 것으로 수정했다.
이 과정에서 여러개의 조건식을 삼항연산자로 사용하는 것은 가독성이 좋지 않아 가능하면 if else로 작성하는 것이 좋으며 쉼표 연산자 또한 거의 사용하지 않는 것이라는 걸 알았다.
아무래도 경험과 기초가 부족해서.. 어 뭐야 써봤는데 되네? 하며 왜 되는지 제대로 알아보지 않아서 이런 오류에 부딪힌 것 같다. 앞으론 잘 알아보고 사용해야겠다🥹
{Array.from({ length: maxPokemonCount - selectPokemon.length }).map(
(_, index) => (
<PokeBall
key={`ball-${index}`}
src="https://react-6-pokemon.vercel.app/assets/pokeball-13iwdk7Y.png"
/>
)
)}
포켓볼 6개를 대시보드에 넣고 포켓몬을 등록하면 포켓볼이 6개가 찌그러지며 포켓몬이 등록되었다.
6개짜리 포켓볼 배열을 만들고 포켓몬을 추가하면 바꿔치기해야하나..? 이렇게 생각했다가 어차피 selectPokemon을 state로 만들어 놨으니까 그 길이에 따라서 포켓볼을 유동적으로 만들어 넣는게 덜 복잡하겠다 싶어서 이렇게 코드를 작성했다.
Array.from 으로 쌩 배열은 처음 만들어 봤는데 내용 없이 길이만 필요한 거라 어렵지 않게 할 수 있었다.
maxPokemonCount = 6 이고 (6 - 선택된 포켓몬 수) 만큼의 배열이 만들어 진다. 이걸 map으로 돌려서 포켓볼로 채워줬다.
const Name = styled.p`
font-size: 33px;
margin-top: 10px;
background: ${(props) =>
props.type.length > 1
? `linear-gradient(45deg, ${getTypeColor(props.type[0])}, ${getTypeColor(
props.type[1]
)})`
: getTypeColor(props.type[0])};
background-clip: text;
color: transparent;
`;
이건 기능은 아니지만 만들고 뿌듯했던 거라 넣었다.
Name 스타일 컴포넌트에 props로 type을 내려주었고, 타입이 2개 이상이면 첫번째 타입과 두번째 타입이 그라데이션 되도록 설정하고 타입이 한개일 경우 해당 타입 색상으로만 나타날 수 있게 설정했다.
getTypeColor 는 포켓몬 타입을 색상으로 변환해주는 함수. case 18개짜리 switch...
생각보다 styled components 사용하는 게 너무 재미있었다. 물론 파일안의 코드가 길어지는게 조금 슬펐지만 요소마다 class값을 따로 지정해주지 않아도 돼서 너무너무 편했다!! 조건부 스타일링도 처음 해봤는데 너무 재미있어서 계속 css만 만지고 싶었음.
리팩토링은... 처음해보는 거라 많이 버벅이긴 했지만 완성은 할 수 있어서 기뻤다. 그 과정에서 무수히 많은 오류들과.. 콘솔로그 이상하게 찍어서 코드 꼬이기 등등.. 사건사고가 있었지만, 코드를 날리거나 하지는 않았으니까...^^!
그래도 context는 이해가 되는데 리덕스 툴킷은 강의도 다시 보고 인터넷 검색도 하고 ai의 도움을 받으면서도.........................
그리고 이런 오류도 봤다.
Error: [Immer] An immer producer returned a new value and modified its draft. Either return a new value or modify the draft.
왜 이렇게 헷갈리고 어렵게 해놓은 건지 모르겠지만 addPokemon 안에서 return 을 잘못 사용하여 일어난 오류였다. 알잘딱으로 설명된 블로그
이젠 팀 프로젝트도 들어가야 하는데 피해 안 주고 잘할 수 있을까 걱정된다...🥹