숙련주차 개인과제를 하면서 alert
기능을 넣었는데 원하는대로 구현이 되지 않았다. 조금 어이없는 실수(?)였는데 똑같은 실수를 하지 않으려고.. 정리해보았다.
카드 6장이 선택된 상태에서 또 <추가> 버튼을 누르면 alert
을 띄우는 것이었다.
🚧 작성한 코드
import styled from "styled-components";
import { useContext } from "react";
import { PokemonContext } from "../context/PokemonContext.jsx";
const Dashboard = () => {
const { selectedPokemon, removePokemon } = useContext(PokemonContext);
if (selectedPokemon.length >= 6) {
alert("최대 6개까지만 선택할 수 있습니다.");
//return; >> 을 쓰면 계속 경고창이 떴음
}
return (
<DashboardContainer>
<h2>나만의 포켓몬</h2>
{selectedPokemon.length === 0 ? (
<p>포켓몬을 선택해주세요.</p>
) : (
<DashboardCardBox>
{selectedPokemon.map((pokemon) => (
<DashboardCard key={pokemon.id}>
<img src={pokemon.img_url} />
{pokemon.korean_name}
<Button onClick={() => removePokemon(pokemon.id)}>삭제</Button>
</DashboardCard>
))}
</DashboardCardBox>
)}
</DashboardContainer>
);
};
export default Dashboard;
selectedPokemon
이라는 State가 값이 변하면서 리렌더링이 되면서 경고창이 2번 떴나?onClick
에 경고창 함수를 넣어주어야 할까?onAdd
함수 만들 때 조건문 넣어보자! > 해결🚧 수정한 코드
import { createContext, useState } from "react";
export const PokemonContext = createContext(null);
export function PokemonProvider({ children }) {
const [selectedPokemon, setSelectedPokemon] = useState([]);
const addPokemon = (pokemon) => {
if (selectedPokemon.length >= 6) {
alert("최대 6개까지만 선택할 수 있습니다.");
return;
// 여기서는 return 써도 ㄱㅊ...
// 조건문 없애고 경고창만 띄우거나 App.jsx 수정
// 추가되는 시점(버튼을 누르는 이벤트를 만드는 곳)에 로직을 작성해야함
}
if (!selectedPokemon.some((item) => item.id === pokemon.id)) {
setSelectedPokemon([...selectedPokemon, pokemon]);
} else {
alert("이미 선택한 포켓몬 입니다.");
return;
}
};
const removePokemon = (pokemonId) => {
const filteredPokemon = selectedPokemon.filter((item) => {
return item.id !== pokemonId;
});
setSelectedPokemon(filteredPokemon);
};
return (
<PokemonContext.Provider
value={{
selectedPokemon,
setSelectedPokemon,
addPokemon,
removePokemon,
}}
>
{children}
</PokemonContext.Provider>
);
}
해결은 했지만 정확한 이유를 알지 못해서 튜터님께 여쭤보았다.
main.jsx
파일에 가면 볼 수 있는데 react는 StrictMode
, 즉 엄격모드 로 실행된다. StrictMode
는 개발 중에 컴포넌트에서 일반적인 버그를 빠르게 찾을 수 있도록 한다.
이것 때문에 우리가 콘솔창을 확인할 때도 늘 2번씩 찍혔던 것이다.
따라서 내가 넣은 alert
창도 이 StrictMode
때문에 2번씩 나왔던 것이다.
Strict Mode를 잠깐 정리하고 가면 아래의 기능을 담당한다.
if (selectedPokemon.length >= 6) {
alert("최대 6개까지만 선택할 수 있습니다.");
return;
우선 해당부분 코드만 보면 선택된 (추가된) 카드의 개수가 6개 이상이면! 경고창이 뜨면서 아래의 함수를 return으로 종료시키는 것이다.
이 경고창을 뜨게 하는건 사용자가 <추가>버튼을 "클릭한 그 시점" 에 위 코드의 조건문을 검사한 후 실행해야한다.
하지만 나는 버튼 클릭이벤트가 없는 Dashboard 컴포넌트에서 뜬금없이 넣어버린 것이다.
const Dashboard = () => {
const { selectedPokemon, removePokemon } = useContext(PokemonContext);
if (selectedPokemon.length >= 6) {
alert("최대 6개까지만 선택할 수 있습니다.");
return;
//조건문 없이 경고창만 써도 2번씩 뜨는 현상은 동일하게 발생
//버튼 클릭하는 이벤트 생성하는 곳에 alert 조건문을 넣어야한다!
버튼 클릭과는 연관이 없고 그냥 카드 개수만 영향을 받게 되니까 if문을 지우고 경고창만 넣어도 똑같은 오류가 생긴다
⭐️ 구현하려는 이벤트가 "어느 시점"에서 실행되어야 하는지 생각하고 코드를 작성하자!
✅ 추가버튼 코드
const addPokemon = (pokemon) => {
if (selectedPokemon.length >= 6) {
alert("최대 6개까지만 선택할 수 있습니다.");
return;
}
if (!selectedPokemon.some((item) => item.id === pokemon.id)) {
setSelectedPokemon([...selectedPokemon, pokemon]);
} else {
alert("이미 선택한 포켓몬 입니다.");
return;
}
};
Dashboard에 있는 카드가 추가되고 없어지니까 당연히 경고창도 여기서 뜨게 하는게 맞다고 아주 단순한 생각으로 작성해버렸다...ㅎ (정리하고나니까 더 창피)
그래도 리액트가 StrictMode
기능으로 검사를 하고 있고 이러한 모든 검사는 개발 전용이며 프로덕션 빌드에는 영향을 미치지 않는다는 솔솔한 정보도 알았다.
여전히 실수 가득한 초보자지만 많이 실수하고 배워나가자..!!🚀🚀
당신은 Strict모드가 필요할 수 있습니다