리액트에서 carousel component 만들기
forwardRef
은 애니메이션을 구현하느라 사용arr
는 이미지가 담긴 배열import React, { useEffect, useState, useRef, forwardRef } from 'react';
import styled from 'styled-components';
import prev from 'assets/icons/arrow-prev.svg';
import next from 'assets/icons/arrow-next.svg';
const Container = styled.div`
position: relative;
width: calc(290px * 4);
height: auto;
margin: 0 auto;
overflow: hidden;
transform: translateY(50px);
opacity: 0;
`;
const SliderContainer = styled.div`
width: 290px;
height: 290px;
display: flex;
`;
const Button = styled.button`
background-color: white;
border-radius: 50%;
width: 50px;
height: 50px;
position: absolute;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: center;
align-items: center;
left: ${(props) => props.direction === 'prev' && '1%'};
right: ${(props) => props.direction === 'next' && '1%'};
z-index: 200;
img {
width: 25%;
height: 25%;
}
`;
const Btn = ({ direction, onClick, img }) => {
return (
<Button onClick={onClick} direction={direction}>
<img src={img} />
</Button>
);
};
const Carousel = forwardRef((props, ref) => {
const [currentSlide, setCurrentSlide] = useState(0);
const slideRef = useRef(null);
const { arr } = props;
const slides = 4; // For total 8 images
const handleNext = () => {
if (currentSlide >= slides) {
setCurrentSlide(0);
} else {
setCurrentSlide(currentSlide + 1);
}
};
const handlePrev = () => {
if (currentSlide === 0) {
setCurrentSlide(slides);
} 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 ref={ref}>
<SliderContainer ref={slideRef}>
{arr.map((img, i) => (
<img src={img} key={i} alt="something" />
))}
</SliderContainer>
<Btn direction="prev" onClick={handlePrev} img={prev} />
<Btn direction="next" onClick={handleNext} img={next} />
</Container>
);
});
export default Carousel;
결과물
한장씩 넘어가게 된다.
import React, { useEffect, useState, useRef } from "react";
import "./styles.css";
import styled from 'styled-components';
const IMG = styled.img`
width: 100%;
height: 70vh;
`;
const Container = styled.div`
width: 60%;
overflow: hidden;
`;
const Button = styled.button`
all: unset;
border: 1px solid coral;
padding: 0.5em 2em;
color: coral;
border-radius: 10px;
&:hover {
transition: all 0.3s ease-in-out;
background-color: coral;
color: #fff;
}
`;
const SliderContainer = styled.div`
width: 100%;
display: flex;
`;
function Slider() {
const [currentSlide, setCurrentSlide] = useState(0);
const slideRef = useRef(null);
const TOTAL_SLIDES = 2;
const images = [img1, img2, img3];
const nextSlide = () => {
if (currentSlide >= TOTAL_SLIDES) {
setCurrentSlide(0);
} else {
setCurrentSlide(currentSlide + 1);
}
};
const prevSlide = () => {
if (currentSlide === 0) {
setCurrentSlide(TOTAL_SLIDES);
} 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>
<SliderContainer ref={slideRef}>
{images.map((img, i) => <IMG src={img} key={i} />)}
</SliderContainer>
<Button onClick={prevSlide}>Previous Slide</Button>
<Button onClick={nextSlide}>Next Slide</Button>
</Container>
);
}
export default Slider;
결과물