728x90
중복된 useState 상태 및 함수코드 정리하는 방법을 알아보자!
만들 예제의 완성본
4개의 버튼을 누르면 각각의 색깔이 연보라에서 진보라로 바뀌게 한다.
1. App.js에 MbtiButton 컴포넌트를 import한다.
App.js
import { MbtiButton } from "./MbtiButton";
import "./styles.css";
export default function App() {
return (
<div className="App">
<MbtiButton />
</div>
);
}
2. MbtiButton.jsx를 마크업한다.
MbtiButton.jsx
import "./MbtiButton.css";
import LightPurpleE from "./assets/E-light-purple.png";
import LightPurpleI from "./assets/I-light-purple.png";
import LightPurpleP from "./assets/P-light-purple.png";
import LightPurpleJ from "./assets/J-light-purple.png";
import DeepPurpleE from "./assets/E-deep-purple.png";
import DeepPurpleI from "./assets/I-deep-purple.png";
import DeepPurpleP from "./assets/P-deep-purple.png";
import DeepPurpleJ from "./assets/J-deep-purple.png";
export const MbtiButton = () => {
return (
<div>
<div className="container">
<span className="title">MBTI BOX</span>
<ul className="mbti-pick-box">
<li>
<button type="button" className="mbti-button">
<img src={LightPurpleI} alt="MBTI I 아이콘"></img>
</button>
</li>
<li>
<button type="button" className="mbti-button">
<img src={LightPurpleE} alt="MBTI E 아이콘"></img>
</button>
</li>
<li>
<button type="button" className="mbti-button">
<img src={LightPurpleJ} alt="MBTI J 아이콘"></img>
</button>
</li>
<li>
<button type="button" className="mbti-button">
<img src={LightPurpleP} alt="MBTI P 아이콘"></img>
</button>
</li>
</ul>
</div>
</div>
);
};
3. 버튼을 누르면 버튼 이미지가 색깔이 바뀌게 한다.
MbtiButton.jsx
import "./MbtiButton.css";
import LightPurpleE from "./assets/E-light-purple.png";
import LightPurpleI from "./assets/I-light-purple.png";
import LightPurpleP from "./assets/P-light-purple.png";
import LightPurpleJ from "./assets/J-light-purple.png";
import DeepPurpleE from "./assets/E-deep-purple.png";
import DeepPurpleI from "./assets/I-deep-purple.png";
import DeepPurpleP from "./assets/P-deep-purple.png";
import DeepPurpleJ from "./assets/J-deep-purple.png";
import { useState } from "react";
export const MbtiButton = () => {
// 이미지 상태
const [imageSrcI, setImageSrcI] = useState(LightPurpleI); // 이미지 초기값은 연보라
// 클릭 상태
const [isClickedI, setIsClickedI] = useState(false); // 클릭 초기값은 false
const [imageSrcE, setImageSrcE] = useState(LightPurpleE);
const [isClickedE, setIsClickedE] = useState(false);
const [imageSrcJ, setImageSrcJ] = useState(LightPurpleJ);
const [isClickedJ, setIsClickedJ] = useState(false);
const [imageSrcP, setImageSrcP] = useState(LightPurpleP);
const [isClickedP, setIsClickedP] = useState(false);
// toggle 함수 구현
// 클릭이 false면, 이미지상태를 진보라로 바꾸고 클릭상태를 true로 바꿈
// 클릭이 true면, 이미지상태를 연보라로 바꾸고 클릭상태를 false로 바꿈
const handleClickI = () => {
if (isClickedI) {
setImageSrcI(LightPurpleI);
setIsClickedI(false);
} else {
setImageSrcI(DeepPurpleI);
setIsClickedI(true);
}
};
const handleClickE = () => {
if (isClickedE) {
setImageSrcE(LightPurpleE);
setIsClickedE(false);
} else {
setImageSrcE(DeepPurpleE);
setIsClickedE(true);
}
};
const handleClickJ = () => {
if (isClickedJ) {
setImageSrcJ(LightPurpleJ);
setIsClickedJ(false);
} else {
setImageSrcJ(DeepPurpleJ);
setIsClickedJ(true);
}
};
const handleClickP = () => {
if (isClickedP) {
setImageSrcP(LightPurpleP);
setIsClickedP(false);
} else {
setImageSrcP(DeepPurpleP);
setIsClickedP(true);
}
};
return (
<div>
<div className="container">
<span className="title">MBTI BOX</span>
<ul className="mbti-pick-box">
<li>
<button
type="button"
className="mbti-button"
onClick={handleClickI} // 클릭상태를 onClick 이벤트에 달아준다.
>
<img src={imageSrcI} alt="MBTI I 아이콘"></img> // 이미지상태를 img src에 달아준다.
</button>
</li>
<li>
<button
type="button"
className="mbti-button"
onClick={handleClickE}
>
<img src={imageSrcE} alt="MBTI E 아이콘"></img>
</button>
</li>
<li>
<button
type="button"
className="mbti-button"
onClick={handleClickJ}
>
<img src={imageSrcJ} alt="MBTI J 아이콘"></img>
</button>
</li>
<li>
<button
type="button"
className="mbti-button"
onClick={handleClickP}
>
<img src={imageSrcP} alt="MBTI P 아이콘"></img>
</button>
</li>
</ul>
</div>
</div>
);
};
그런데 이런식으로 코드를 작성하면, 코드가 너무 길어지는 문제점이 생긴다.
4. 이미지 data를 따로 분리해서 만들고, <li> 부분을 컴포넌트로 분리해서 상태관리를 따로 한다. 이렇게 하면 코드가 깔끔해진다.
MbtiButton.jsx
import { data } from "./data";
import { MbtiBox } from "./MbtiBox";
import "./MbtiButton.css";
export const MbtiButton = () => {
return (
<div>
<div className="container">
<span className="title">MBTI BOX</span>
<div className="mbti-pick-box-container">
<ul className="mbti-pick-box">
{data.map((e) => {
return <MbtiBox key={e.id} data={e} />;
})}
</ul>
</div>
</div>
</div>
);
};
data.js
import LightPurpleE from "./assets/E-light-purple.png";
import LightPurpleI from "./assets/I-light-purple.png";
import LightPurpleP from "./assets/P-light-purple.png";
import LightPurpleJ from "./assets/J-light-purple.png";
import DeepPurpleE from "./assets/E-deep-purple.png";
import DeepPurpleI from "./assets/I-deep-purple.png";
import DeepPurpleP from "./assets/P-deep-purple.png";
import DeepPurpleJ from "./assets/J-deep-purple.png";
export const data = [
{
id: 1,
light_purple: LightPurpleI,
deep_purple: DeepPurpleI,
alt: "알파벳 I 이미지",
},
{
id: 2,
light_purple: LightPurpleE,
deep_purple: DeepPurpleE,
alt: "알파벳 E 이미지",
},
{
id: 3,
light_purple: LightPurpleJ,
deep_purple: DeepPurpleJ,
alt: "알파벳 J 이미지",
},
{
id: 4,
light_purple: LightPurpleP,
deep_purple: DeepPurpleP,
alt: "알파벳 P 이미지",
},
];
MbtiBox.jsx
import { useState } from "react";
export const MbtiBox = ({ data }) => { // data를 props로 받아오기
// toggle 함수 구현, 초기값은 false
const [toggle, setToggle] = useState(false);
return (
<li>
<button
type="button"
className="mbti-button"
onClick={() => {
setToggle((toggle) => !toggle); // 클릭하면 toggle의 상태를 반대로 바꾼다.
}}
>
<img
src={toggle ? data.deep_purple : data.light_purple} // toggle이 true면, data의 진보라를 가져오고, false면 data의 연보라를 가져온다.
alt={data.alt} // 대체 텍스트도 data에서 가져온다.
/>
</button>
</li>
);
};
아래와 같이 alt 값도 잘 적용된 것을 볼 수 있다.
728x90
'Libraries > React' 카테고리의 다른 글
[React] 스크롤 top 버튼 기능 구현하기 (0) | 2024.01.07 |
---|---|
[React] 작성 날짜 기준으로 지난 시간을 변환하기 (리뷰시간, 게시글 시간, 댓글시간, 방금전, 몇분전, 몇시간전, 며칠전) (2) | 2024.01.06 |
[React] Routing (5) 데이터에서 route 설정하기 (0) | 2024.01.03 |
[React] Filter (3) 리스트 카테고리 필터링 (0) | 2023.12.31 |
[React] Filter (2) 검색창, 검색어, 검색 필터 기능 구현 (검색창 만들기) (2) | 2023.12.28 |