▶ 이미지 배치를 1개, 2개, 3개, 4개일 때 이미지 다르게 배치
▶ 참고한 유튜브 강의
const Test6 = () => {
return (
<>
<h1>이미지 1개</h1>
<div className="">
<div className="bg-red-500 rounded-lg shadow-xl min-h-[50px]" />
</div>
<h1>이미지 2개</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-2 gap-y-3">
<div className="bg-orange-500 rounded-lg shadow-xl min-h-[50px]" />
<div className="bg-yellow-500 rounded-lg shadow-xl min-h-[50px]" />
</div>
<h1>이미지 3개</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-2 gap-y-3">
<div className="bg-green-500 rounded-lg shadow-xl min-h-[50px] row-span-2" />
<div className="bg-teal-500 rounded-lg shadow-xl min-h-[50px]" />
<div className="bg-blue-500 rounded-lg shadow-xl min-h-[50px]" />
</div>
<h1>이미지 4개</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-2 gap-y-3">
<div className="bg-indigo-500 rounded-lg shadow-xl min-h-[50px]" />
<div className="bg-purple-500 rounded-lg shadow-xl min-h-[50px]" />
<div className="bg-pink-500 rounded-lg shadow-xl min-h-[50px]" />
<div className="bg-slate-500 rounded-lg shadow-xl min-h-[50px]" />
</div>
</>
);
};
export default Test6;
▶ 개별 이미지 선택할 때 해당 이미지가 보여지도록 함
이미지 클릭 후 onZoom을 통해 ImageZoomModal로 이동 시 이미지 이름(imgName)과 숫자(num) 전달
첫 번째 이미지 -> 숫자 0
두 번째 이미지 -> 숫자 1
세 번째 이미지 -> 숫자 2
네 번째 이미지 -> 숫자 3
const [showImg, setShowImg] = useState("");
const [showNum, setShowNum] = useState(0);
const onZoom = useCallback(
(imgName, num) => () => {
setShowNum(num);
setShowImg(imgName);
setShowImagesZoom(true);
},
[]
);
return (
<img src={`http://localhost:3005/${images[0]?.src}`}
alt={images[0]?.src}
className="rounded-lg shadow-xl min-h-[50px]"
onClick={onZoom(images[0]?.src, 0)}
/>
{showImagesZoom && (
<ImagesZoomModal
images={images}
onClose={onClose}
showImg={showImg} //이미지 이름
showNum={showNum} //이미지 개별 숫자
/>
)}
)
▶ 해당 이미지 선택 시 왼쪽, 오른쪽 슬라이더 기능 되도록 함
처음 이미지 클릭 시 클릭한 이미지 보여줄 것
두 번째 즉 왼쪽(leftButton) 혹은 오른쪽 버튼(rightButton) 클릭 시 처음 이미지 보여지지 않고 전달 받은 images에서 보여줄 것
mainImage true면 첫 이미지 보여줌 false면 이미지 보이지 않음
hideImages true면 슬라이더 되는 이미지 보여줌 false면 이미지 보여지 않음
//props로 전달받은 값들
const ImagesZoomModal = ({ showNum, showImg, images, onClose }) => {
const [open, setOpen] = useState(true);
const [num, setNum] = useState(showNum); //전달받은 숫자
const [mainImage, setMainImage] = useState(true);
const [hideImages, setHideImages] = useState(false);
const leftButton = () => {
setMainImage(false);
setHideImages(true);
if (num >= 1) { //가장 왼쪽에 있을 때 더 이상 클릭 안 됨
setNum(num - 1);
}
};
const rightButton = () => {
setMainImage(false);
setHideImages(true);
const imgLength = images.length - 1;
if (num < imgLength) { //가장 오른쪽에 있을 때 더 이상 클릭 안 됨
setNum(num + 1);
}
};
return (
<>
<section>
<div className="relative">
{mainImage ? (
<img
className="h-full w-full rounded-lg object-cover"
src={`http://localhost:3005/${showImg}`}
alt={showImg}
/>
) : null}
<ul id="slider">
{hideImages
? images.map((v, i) => (
<li
name="slide"
className={`h-full w-full rounded-lg relative ${
num === i ? null : "hidden"
}`}
// className={`h-[50vh] relative`}
key={v.id}
>
<img
className="h-full w-full rounded-lg object-cover"
src={`http://localhost:3005/${v.src}`}
alt={v?.src}
/>
</li>
))
: null}
</ul>
{images.length === 1 ? null : (
<div className="absolute px-5 flex h-full w-full top-0 left-0">
<div className="my-auto w-full flex justify-between">
<button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
<ChevronLeftIcon
onClick={leftButton}
className="w-5 h-5"
/>
</button>
<button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
<ChevronRightIcon
onClick={rightButton}
className="w-5 h-5"
/>
</button>
</div>
</div>
)}
</div>
</section>
</>
);
};
export default ImagesZoomModal;
form 태그 안에 button이 두 개 존재한 상황
-> form 태그에서 submit 담당하는 경우 type="submit", 다른 하나는 type="button"
<button
type="button"
onClick={onClickImageUpload}
className="ml-2 bg-gray-100"
>
이미지 추가
</button>
</div>
<button
type="submit"
className="flex hover:bg-light-green hover:text-white hover:rounded-md"
>
<PencilIcon className="h-5 w-5 md:h-8 md:w-8 lg:h-8 lg:w-8" />
<h3 className="mt-1 mr-2 font-bold hover:text-white">추가</h3>
</button>
▶ flowbite의 js 파일을 다운 받아야 작동 가능
▶ 실제 이미지 슬라이더에 참고한 것 (유튜브 강의)
▶ document is undefined 오류(react)
useRef를 통해 childElementCount 이용하기
document.getElementById 대신 useRef 이용
DOM 조작 시 useRef를 사용함(game부분을 useRef를 사용해 수정할 것)
▶ [useRef로 classList.remove, add]
//document 이용(JS)
const sliderElement = document.getElementById("slider");
const totalSlides = sliderElement.childElementCount;
console.log("totalSlides", totalSlides); //3
//리액트에서 사용 원할 경우 해당 변수들을 useEffect 안에 넣을 것
useEffect(() => {
const sliderElement = document.getElementById("slider");
const totalSlides = sliderElement.childElementCount;
console.log("totalSlides", totalSlides);
}, []);
return (
<ul id="slider" >
<li>
<img
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div>
<h2>
Some Big Heading 1
</h2>
</div>
</li>
<li>
<img
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div>
<h2>
Some Big Heading 2
</h2>
</div>
</li>
<li>
<img
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div>
<h2>
Some Big Heading 3
</h2>
</div>
</li>
</ul>
)
//useRef 이용
const totalSlides = useRef(null);
const innerElements = totalSlides.current.innerHTML;
let count = (innerElements.match(/<li/g) || []).length; //li값이 몇 개 있는지
console.log("count", count); //3
return (
<ul id="slider" ref={totalSlides}>
<li>
<img
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div>
<h2>
Some Big Heading 1
</h2>
</div>
</li>
<li>
<img
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div>
<h2>
Some Big Heading 2
</h2>
</div>
</li>
<li>
<img
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div>
<h2>
Some Big Heading 3
</h2>
</div>
</li>
</ul>
)
import React, { useCallback, useEffect, useState, useRef } from "react";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
const Test = () => {
const [id, setId] = useState(1);
const totalSlides = useRef(null);
const leftButton = () => {
if (currentSlideId > 1) {
setId(id - 1);
}
};
const rightButton = () => {
const innerElements = totalSlides.current.innerHTML;
let count = (innerElements.match(/<li/g) || []).length; //3
if (currentSlideId < count) {
setId(id + 1);
}
};
return (
<>
{console.log("id 결과", id)}
<section>
<div className="relative">
<ul id="slider" ref={totalSlides}>
<li
name="slide"
className={`h-[50vh] relative ${id === 1 ? null : "hidden"}`}
>
<img
className="h-full w-full object-cover"
src="https://placeimg.com/1200/800/nature"
alt=""
/>
<div className="absolute top-0 left-0 h-full w-full flex">
<h2 className="text-4xl font-bold text-white my-auto w-full text-center text-center px-20">
Some Big Heading 1
</h2>
</div>
</li>
<li
name="slide"
className={`h-[50vh] relative ${id === 2 ? null : "hidden"}`}
>
<img
className="h-full w-full object-cover"
src="https://placeimg.com/1200/800/animals"
alt=""
/>
<div className="absolute top-0 left-0 h-full w-full flex">
<h2 className="text-4xl font-bold text-white my-auto w-full text-center text-center px-20">
Some Big Heading 2
</h2>
</div>
</li>
<li
name="slide"
className={`h-[50vh] relative ${id === 3 ? null : "hidden"}`}
>
<img
className="h-full w-full object-cover"
src="https://placeimg.com/1200/800/tech"
alt=""
/>
<div className="absolute top-0 left-0 h-full w-full flex">
<h2 className="text-4xl font-bold text-white my-auto w-full text-center text-center px-20">
Some Big Heading 3
</h2>
</div>
</li>
</ul>
<div className="absolute px-5 flex h-full w-full top-0 left-0">
<div className="my-auto w-full flex justify-between">
<button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
<ChevronLeftIcon onClick={leftButton} className="w-5 h-5" />
</button>
<button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
<ChevronRightIcon onClick={rightButton} className="w-5 h-5" />
</button>
</div>
</div>
</div>
</section>
</>
);
};
export default Test;