
import React,{useState, useContext} from "react";
import { UserContext } from "@/pages/_app";
import styles from "./index.module.css";
import Link from "next/link";
export default function Portfolio() {
const languageList = useContext(UserContext);
const [isFirst, setIsFirst] = useState(false);
const [isSecond, setIsSecond] = useState(false);
const [isThird, setIsThird] = useState(false);
const [isFourth, setIsFourth] = useState(false);
const [isFirstClick, setIsFirstClick] = useState(false);
const [isSecondClick, setIsSecondClick] = useState(false);
const [isThirdClick, setIsThirdClick] = useState(false);
const [isFourthClick, setIsFourthClick] = useState(false);
const [isFirstMouseLeave, setIsFirstMouseLeave] = useState(true);
const [isSecondMouseLeave, setIsSecondMouseLeave] = useState(true);
const [isThirdMouseLeave, setIsThirdMouseLeave] = useState(true);
const [isFourthMouseLeave, setIsFourthMouseLeave] = useState(true);
const firstOnMouseLeave = () => {
setIsFirst(false);
setIsFirstMouseLeave(false);
setIsFirstClick(false);
}
const secondOnMouseLeave = () => {
setIsSecond(false);
setIsSecondMouseLeave(false);
setIsSecondClick(false);
}
const thirdOnMouseLeave = () => {
setIsThird(false);
setIsThirdMouseLeave(false);
setIsThirdClick(false);
}
const fourthOnMouseLeave = () => {
setIsFourth(false);
setIsFourthMouseLeave(false);
setIsFourthClick(false);
}
const firstClicked = () => {
setIsFirstClick(!isFirstClick);
setIsFirstMouseLeave(true);
}
const secondClicked = () => {
setIsSecondClick(!isFirstClick);
setIsSecondMouseLeave(true);
}
const thirdClicked = () => {
setIsThirdClick(!isFirstClick);
setIsThirdMouseLeave(true);
}
const fourthClicked = () => {
setIsFourthClick(!isFirstClick);
setIsFourthMouseLeave(true);
}
return (<>
<div className={styles.container}>
<div className={`${styles.background}
${isFirst && styles.first_column_background}
${isSecond && styles.second_column_background}
${isThird && styles.third_column_background}
${isFourth && styles.fourth_column_background}
`}>
<div className={styles.first_column}
onMouseEnter={() => setIsFirst(true)}
onMouseLeave={firstOnMouseLeave}>
<div className={styles.first_column_title}>
{languageList.state.language === "English" ? "Skin Tightening" : "스킨 타이트닝"}
</div>
{isFirstClick && isFirstMouseLeave && firstServices}
{isFirst && <div className={styles.first_column_learn}>
<span className={styles.span} onClick={firstClicked}>
{languageList.state.language === "English" ? "Learn More" : "더 알아보기"}
</span>
</div>}
</div>
<div className={styles.second_column}
onMouseEnter={() => setIsSecond(true)}
onMouseLeave={secondOnMouseLeave}>
<div className={styles.second_column_title}>
{languageList.state.language === "English" ? "Acne Treatment" : "여드름 치료"}
</div>
{isSecondClick && isSecondMouseLeave && secondServices}
{isSecond && <div className={styles.second_column_learn}>
<span className={styles.span2} onClick={secondClicked} >
{languageList.state.language === "English" ? "Learn More" : "더 알아보기"}
</span>
</div>}
</div>
<div className={styles.third_column}
onMouseEnter={() => setIsThird(true)}
onMouseLeave={thirdOnMouseLeave}>
<div className={styles.third_column_title}>
{languageList.state.language === "English" ? "Pigmentation" : "피부색소침착"}
</div>
{isThirdClick && isThirdMouseLeave && thirdServices}
{isThird && <div className={styles.third_column_learn}>
<span className={styles.span} onClick={thirdClicked}>
{languageList.state.language === "English" ? "Learn More" : "더 알아보기"}
</span>
</div>}
</div>
<div className={styles.fourth_column}
onMouseEnter={() => setIsFourth(true)}
onMouseLeave={fourthOnMouseLeave}>
<div className={styles.fourth_column_title}>
{languageList.state.language === "English" ? "Pores" : "모공"}
</div>
{isFourthClick && isFourthMouseLeave && fourthServices}
{isFourth && <div className={styles.fourth_column_learn}>
<span className={styles.span} onClick={fourthClicked}>
{languageList.state.language === "English" ? "Learn More" : "더 알아보기"}
</span>
</div>}
</div>
</div>
</div>
</>
);
}
import React, { useState, useContext, useEffect } from 'react'
import { UserContext } from '@/pages/_app'
import styles from './index.module.css'
import Link from 'next/link'
import Image from 'next/image'
import CoverImage from 'public/portfolio/4.jpg'
import Image1 from 'public/portfolio/5.png'
import Image2 from 'public/portfolio/2.jpg'
import Image3 from 'public/portfolio/pigmentation.png'
import Image4 from 'public/portfolio/6.jpg'
const IMAGES = {
SkinTightening: { src: Image1.src, alt: 'SkinTightening' },
AcneTreatment: { src: Image2.src, alt: 'AcneTreatment' },
Pigmentation: { src: Image3.src, alt: 'Pigmentation' },
Pores: { src: Image4.src, alt: 'Pores' },
}
export default function Portfolio() {
const languageList = useContext(UserContext)
const [hover, setHover] = useState(null)
const [selected, setSelected] = useState(null)
useEffect(() => setSelected(null), [hover])
const handleMouseOver = (type) => setHover(type)
const handleMouseClick = (type) => setSelected(type)
const handleMouseLeave = () => setHover(null)
return (
<div className={styles.container}>
<div
className={styles.background}
style={{
backgroundImage: hover
? `url(${IMAGES[hover].src})`
: `url(${CoverImage.src})`,
}}
onMouseLeave={handleMouseLeave}
>
<div
className={styles.first_column}
onMouseEnter={() => handleMouseOver('SkinTightening')}
>
<div className={styles.first_column_title}>
{languageList.state.language === 'English'
? 'Skin Tightening'
: '스킨 타이트닝'}
</div>
{selected === 'SkinTightening' && firstServices}
{hover === 'SkinTightening' && (
<div className={styles.first_column_learn}>
<span
className={styles.span}
onClick={() => handleMouseClick('SkinTightening')}
>
{languageList.state.language === 'English'
? 'Learn More'
: '더 알아보기'}
</span>
</div>
)}
</div>
<div
className={styles.second_column}
onMouseEnter={() => handleMouseOver('AcneTreatment')}
>
<div className={styles.second_column_title}>
{languageList.state.language === 'English'
? 'Acne Treatment'
: '여드름 치료'}
</div>
{selected === 'AcneTreatment' && secondServices}
{hover === 'AcneTreatment' && (
<div className={styles.second_column_learn}>
<span
className={styles.span2}
onClick={() => handleMouseClick('AcneTreatment')}
>
{languageList.state.language === 'English'
? 'Learn More'
: '더 알아보기'}
</span>
</div>
)}
</div>
<div
className={styles.third_column}
onMouseEnter={() => handleMouseOver('Pigmentation')}
>
<div className={styles.third_column_title}>
{languageList.state.language === 'English'
? 'Pigmentation'
: '피부색소침착'}
</div>
{selected === 'Pigmentation' && thirdServices}
{hover === 'Pigmentation' && (
<div className={styles.third_column_learn}>
<span
className={styles.span}
onClick={() => handleMouseClick('Pigmentation')}
>
{languageList.state.language === 'English'
? 'Learn More'
: '더 알아보기'}
</span>
</div>
)}
</div>
<div
className={styles.fourth_column}
onMouseEnter={() => handleMouseOver('Pores')}
>
<div className={styles.fourth_column_title}>
{languageList.state.language === 'English' ? 'Pores' : '모공'}
</div>
{selected === 'Pores' && fourthServices}
{hover === 'Pores' && (
<div className={styles.fourth_column_learn}>
<span
className={styles.span}
onClick={() => handleMouseClick('Pores')}
>
{languageList.state.language === 'English'
? 'Learn More'
: '더 알아보기'}
</span>
</div>
)}
</div>
</div>
</div>
)
}
🔎 누가봐도 다르게 상태값이 확 줄었다.
전 코드에서는 isFirst부터 isFourth까지 4개의 섹션마다 각각 hover, click, mouseLeave 상태값을 관리하고 있습니다.
이러한 상태값을 모두 조합하면 총 12개의 상태값이 필요합니다.
예를 들어, 첫 번째 섹션의 경우 hover, click, mouseLeave 상태값을 각각 isFirst, isFirstClick, isFirstMouseLeave으로 관리합니다.
바뀐 후 코드에서는
상태값을 hover와 selected 두 가지로 간소화하여 관리합니다. hover는 마우스가 올라간 상태를, selected는 클릭된 상태를 나타냅니다. 이렇게 함으로써 상태값을 총 2개만 사용하여 총 경우의 수가 2^2 = 4로 감소합니다.

전 코드에서는 각 섹션의 배경 이미지를 백그라운드 스타일로 설정하고 있습니다.
바뀐 후 코드에서는 이미지를 IMAGES 객체에 저장하고, 해당 이미지를 동적으로 로드하여 배경 이미지로 설정합니다.
이전 코드에서는 각 섹션의 마우스 이벤트(mouseEnter, mouseLeave, click)에 대한 핸들러 함수를 별도로 정의하고, 각각의 상태값을 관리하고 있습니다. 마우스가 해당 섹션 위로 올라갔을 때와 클릭되었을 때를 별도의 상태값으로 관리하며, 해당 섹션을 떠나면 다시 초기화되는 상태값도 사용합니다.
새로운 코드에서는 마우스 이벤트 핸들러를 하나로 통합하고, 상태값을 useEffect 훅을 사용하여 관리합니다.
useEffect(() => setSelected(null), [hover])이를 통해 코드가 더 간결해지고 관리하기 쉬워집니다. 부모 컨테이너에 마우스 이벤트를 설정하고, 각 섹션의 상태값에 따라 동작을 결정함으로써 코드의 중복을 줄이고 유지보수성을 높일 수 있습니다.
정리
상태 관리를 위해 hover와 selected라는 두 가지 상태를 사용.
hover 상태는 사용자가 마우스를 올려놓은 이미지 카테고리의 유형을 저장하고, selected 상태는 사용자가 클릭한 이미지 카테고리의 유형을 저장.
useEffect 훅을 사용하여 hover 상태가 변경될 때마다 selected 상태를 초기화하고 있습니다.
이후에는 마우스 이벤트를 처리하는 핸들러 함수들을 정의하고 있습니다.
handleMouseOver 함수는 마우스가 이미지 카테고리 위에 올라갔을 때 실행되며,
해당 이미지 카테고리의 유형을 hover 상태로 설정합니다.
handleMouseClick 함수는 이미지 카테고리가 클릭되었을 때 실행되며, 해당 이미지 카테고리의 유형을 selected 상태로 설정합니다.
handleMouseLeave 함수는 마우스가 이미지 카테고리를 벗어났을 때 실행되며, hover 상태를 초기화합니다.