자식 컴포넌트로 props를 통해 필요한 값 전달하기
부모 컴포넌트인 Main
에서 모바일 화면 여부, 이미지 주소와 캡션, 클릭 이벤트에 해당하는 값을 넘겨준다.
export default function Main() {
// ...
const [showImage, setShowImage] = useState<boolean>(false);
const [imgSrc, setImgSrc] = useState<string>("");
const [imgAlt, setImgAlt] = useState<string>("");
const [windowWidth, setWindowWidth] = useState<number>(window.innerWidth);
const isMobile: boolean = windowWidth < 630;
// ...
return (
<div className={isMobile ? styles["mobile-icon-container"] : ""}>
{showImage && (
<ImageModal isMobile={isMobile} src={imgSrc} alt={imgAlt} onClick={handleModalClick} />
)}
// ...
</div>
);
}
handleImageClick
함수를 실행(이미지 타입 아이콘을 클릭)하면 showImage
의 상태가 true로 변경되면서 모달이 보이게 되는 원리이다.
function Icons({ setImgSrc, setImgAlt, setShowImage, language, isMobile }: IconsProps) {
const handleImageClick = (path: string) => {
if (path === "readme") {
setImgSrc(`/divdivdiv/readme-${language}.webp`);
} else {
setImgSrc(`/divdivdiv/${path}.webp`);
}
setImgAlt(path);
setShowImage(true);
};
// ...
return (
// ...
);
}
반대로 모달을 클릭하면 showImage
의 상태가 false로 변경되어 실행되었던 모달이 사라지게 된다.
export default function Main() {
// ...
const handleModalClick = () => {
setShowImage(false);
setImgSrc("");
setImgAlt("");
};
return (
// ...
);
}
모달 컴포넌트
모달은 다음과 같이 구성되어 있다. 렌더링 시 현재 윈도우의 너비와 높이를 확인해 해당 크기에 적당한 비율로 이미지를 확대하거나 축소시킨다. 또한 모바일 화면일 때(isMobile
이 true)는 모바일 환경에 맞는 스타일을 준다. 모달 이미지의 경우 크게 사진과 리드미 타입으로 나뉘는데, 리드미일 때는 별도의 컴포넌트를 표시한다.
export const ImageModal = ({ isMobile, src, alt, onClick }: ImageModalProps) => {
// ...
const [windowWidth, setWindowWidth] = useState<number>(window.innerWidth);
const [windowHeight, setWindowHeight] = useState<number>(window.innerHeight);
let height: number = windowHeight / 1.2;
let width: number = windowHeight * 0.65;
if (isMobile) {
width = windowWidth * 0.9;
height = width * 1.3;
if (alt === "readme") {
width = windowWidth * 0.9;
height = width * 1.6;
}
}
function ReadmeComponent(props: { path: string; icon: any }) {
const { path, icon } = props;
return (
// ...
);
}
return alt === "readme" ? (
<div className={styles["modal-container"]} onClick={onClick}>
<div className={styles["modal"]} style={{ width: width, height: height }}>
<div
className={styles["last-updated"]}
style={
isMobile ? { margin: "10px 0 0 0" } : { margin: "0 0 30px 0", paddingTop: "10px" }
}
>
{readme.lastUpdated.text[language]}
</div>
<ReadmeComponent path="https://blog.divdivdiv.com" icon={readme.blog} />
<ReadmeComponent path="/music" icon={readme.music} />
// ...
</div>
</div>
) : (
<div className={styles["modal-image"]} onClick={onClick}>
<Image src={src} alt={alt} width={width} height={height} />
</div>
);
};