React의 useState, useEffect, useRef을 이용하여 캐러셀 슬라이더를 만들어 보겠습니다.
create-react-app을 통해 리액트 프로젝트를 만들어 줍니다. 스타일링은 styled-components를 사용하겠습니다.
$ yarn create react-app react-carousel
$ yarn add styled-components
Slider의 요소가 될 Slide 컴포넌트를 만들어 줍니다.
import React from 'react';
import styled from 'styled-components';
export default function Slide({ img }) {
return <IMG src={img} />;
}
const IMG = styled.img`
width: 500px;
height: 500px;
`;
이미지 파일을 props로 받고 보여줍니다.
Slider.js 파일에 캐러셀에 들어갈 이미지들과
import img1 from './img/1.png';
import img2 from './img/2.png';
import img3 from './img/3.png';
이미지를 담을 Slide
import Slide from './Slide';
React Hooks, styled-components를 가져옵니다.
import React, { useState, useRef, useEffect } from 'react';
import styled from 'styled-components';
import React from 'react';
import styled from 'styled-components';
import Slide from './Slide';
import img1 from './img/1.png';
import img2 from './img/2.png';
import img3 from './img/3.png';
const Container = styled.div`
width: 500px;
margin: auto;
height: 1000px;
overflow: hidden; // 선을 넘어간 이미지들은 숨겨줍니다.
`;
const Button = styled.div`
all: unset;
padding: 1em 2em;
margin: 2em 2em;
color: burlywood;
border-radius: 10px;
border: 1px solid burlywood;
&:hover {
background-color: burlywood;
color: #fff;
}
`;
const SliderContainer = styled.div`
margin: 0 auto;
margin-bottom: 2em;
display: flex; // 이미지들을 가로로 나열합니다.
`;
const Text = styled.div`
text-align: center;
color: burlywood;
p {
color: #fff;
font-size: 20px;
background-color: burlywood;
display: inline-block;
border-radius: 50px;
padding: 0.5em 1em;
}
`;
const Center = styled.div`
text-align: center;
`;
const TOTAL_SLIDES = 2; // 전체 슬라이드 개수
export default function Slider() {
return (
<Container>
<Text>
<h1>호두 아가 시절</h1>
<p>n번 째 사진</p>
</Text>
<SliderContainer>
<Slide img={img1} />
<Slide img={img2} />
<Slide img={img3} />
</SliderContainer>
<Center>
<Button>Prev</Button>
<Button>Next</Button>
</Center>
</Container>
);
}
전체 슬라이드의 개수를 지정해 줍니다. 배열처럼 0부터 시작하여 총 3개의 이미지를 사용했으므로 TOTAL_SLIDES = 2를 추가해 줍니다.
const TOTAL_SLIDES=2
const [currentSlide, setCurrentSlide] = useState(0);
const slideRef = useRef(null);
if else 문을 통해 더 이상 넘어갈 슬라이드가 없을 경우 아래 2가지 방법을 사용하여 경우에 따라 다르게 사용할 수 있습니다.
저는 1번째 사진으로 넘어가는 방식을 사용하였습니다.
// Next 버튼 클릭 시
const NextSlide = () => {
if (currentSlide >= TOTAL_SLIDES) {
// 더 이상 넘어갈 슬라이드가 없으면
setCurrentSlide(0); // 1번째 사진으로 넘어갑니다.
// return; // 클릭이 작동하지 않습니다.
} else {
setCurrentSlide(currentSlide + 1);
}
};
// Prev 버튼 클릭 시
const PrevSlide = () => {
if (currentSlide === 0) {
setCurrentSlide(TOTAL_SLIDES); // 마지막 사진으로 넘어갑니다.
// return; // 클릭이 작동하지 않습니다.
} else {
setCurrentSlide(currentSlide - 1);
}
};
<Button onClick={PrevSlide}>Prev</Button>
<Button onClick={NextSlide}>Next</Button>
useEffect(() => {
slideRef.current.style.transition = 'all 0.5s ease-in-out';
slideRef.current.style.transform = `translateX(-${currentSlide}00%)`; // 백틱을 사용하여 슬라이드로 이동하는 에니메이션을 만듭니다.
}, [currentSlide]);
import React, { useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import Slide from './Slide';
import img1 from './img/1.png';
import img2 from './img/2.png';
import img3 from './img/3.png';
const TOTAL_SLIDES = 2; // 전체 슬라이드 개수(총3개. 배열로 계산)
export default function Slider() {
const [currentSlide, setCurrentSlide] = useState(0);
const slideRef = useRef(null);
// Next 버튼 클릭 시
const NextSlide = () => {
if (currentSlide >= TOTAL_SLIDES) {
// 더 이상 넘어갈 슬라이드가 없으면
setCurrentSlide(0); // 1번째 사진으로 넘어갑니다.
// return; // 클릭이 작동하지 않습니다.
} else {
setCurrentSlide(currentSlide + 1);
}
};
// Prev 버튼 클릭 시
const PrevSlide = () => {
if (currentSlide === 0) {
setCurrentSlide(TOTAL_SLIDES); // 마지막 사진으로 넘어갑니다.
// return; // 클릭이 작동하지 않습니다.
} else {
setCurrentSlide(currentSlide - 1);
}
};
useEffect(() => {
slideRef.current.style.transition = 'all 0.5s ease-in-out';
slideRef.current.style.transform = `translateX(-${currentSlide}00%)`; // 백틱을 사용하여 슬라이드로 이동하는 에니메이션을 만듭니다.
}, [currentSlide]);
return (
<Container>
<Text>
<h1>호두 아가 시절</h1>
<p>{currentSlide + 1}번 째 사진</p>
</Text>
<SliderContainer ref={slideRef}>
<Slide img={img1} />
<Slide img={img2} />
<Slide img={img3} />
</SliderContainer>
<Center>
<Button onClick={PrevSlide}>Prev</Button>
<Button onClick={NextSlide}>Next</Button>
</Center>
</Container>
);
}
const Container = styled.div`
width: 500px;
margin: auto;
height: 1000px;
overflow: hidden; // 선을 넘어간 이미지들은 숨겨줍니다.
`;
const Button = styled.div`
all: unset;
padding: 1em 2em;
margin: 2em 2em;
color: burlywood;
border-radius: 10px;
border: 1px solid burlywood;
cursor: pointer;
&:hover {
background-color: burlywood;
color: #fff;
}
`;
const SliderContainer = styled.div`
margin: 0 auto;
margin-bottom: 2em;
display: flex; // 이미지들을 가로로 나열합니다.
`;
const Text = styled.div`
text-align: center;
color: burlywood;
p {
color: #fff;
font-size: 20px;
background-color: burlywood;
display: inline-block;
border-radius: 50px;
padding: 0.5em 1em;
}
`;
const Center = styled.div`
text-align: center;
`;
import Slider from './Slider';
function App() {
return (
<div>
<Slider />
</div>
);
}
export default App;
- 해당 코드는 GitHub 에서 볼 수 있습니다.
- 본 글은 peppermint100을 참고하여 작성되었음을 밝힙니다.
- React를 공부하는 중이고, 복습하는 겸 포스팅을 하고 있기 때문에, 틀린 정보가 있을 수 있습니다.
잘못된 정보가 있다면 댓글로 알려주세요 :)
호두 넘 귀엽네요ㅎㅎ 참고해서 만들어볼게요~친절한 설명 감사합니다!