AnimatePresence
컴포넌트를 활용하여 요소들이 슬라이드 되어 보이는 효과를 줍니다.AnimatePresence
와 다른 점은 배열, key
프로퍼티 등만 다르고 initial
, animate
, exit
props 를 사용하는 것은 같습니다.const boxVariants = {
invisible: { x: -500, opacity: 0, scale: 0 },
visible: {
x: 0,
opacity: 1,
scale: 1,
transition: {
duration: 1,
},
},
exit: {
x: 500,
opacity: 0,
scale: 0,
rotateX: 180,
transition: {
duration: 1,
},
},
};
function App() {
const [visible, setVisible] = useState(1);
const prevPlease = () => setVisible((prev) => (prev === 1 ? 1 : prev - 1));
const nextPlease = () => setVisible((prev) => (prev === 10 ? 10 : prev + 1));
return (
<Wrapper>
<AnimatePresence>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((i) =>
i === visible ? (
<Box
variants={boxVariants}
initial="invisible"
animate="visible"
exit="exit"
key={i}
>
{i}
</Box>
) : null
)}
</AnimatePresence>
<button onClick={prevPlease}>Prev</button>
<button onClick={nextPlease}>Next</button>
</Wrapper>
key
프로퍼티 사용 : 리액트는 html 요소의 key
프로퍼티의 값이 변하면 새로운 요소로 인식합니다.const boxVariants = {
entry: { x: 500, opacity: 0, scale: 0 },
center: {
x: 0,
opacity: 1,
scale: 1,
transition: {
duration: 1,
},
},
exit: {
x: -500,
opacity: 0,
scale: 0,
rotateX: 180,
transition: {
duration: 1,
},
},
};
function App() {
const [visible, setVisible] = useState(1);
const nextPlease = () => setVisible((prev) => (prev === 10 ? 10 : prev + 1));
const prevPlease = () => setVisible((prev) => (prev === 1 ? 1 : prev - 1));
return (
<Wrapper>
<AnimatePresence>
<Box
variants={boxVariants}
initial="entry"
animate="center"
exit="exit"
key={visible}
>
{visible}
</Box>
</AnimatePresence>
<button onClick={prevPlease}>Prev</button>
<button onClick={nextPlease}>Next</button>
</Wrapper>
);
}
initial
프로퍼티 값과 exit
프로퍼티 값을 변경해주면 됩니다.custom
프로퍼티variants
에 데이터를 보낼 수 있게 해주는 프로퍼티 입니다.variants
가 객체가 아닌 객체를 반환하는 함수로 바뀌어야 합니다.const boxVariants = {
entry: (isBack: boolean) => ({
x: isBack ? -500 : 500,
opacity: 0,
scale: 0,
rotateX: -180,
}),
center: {
x: 0,
opacity: 1,
scale: 1,
rotateX: 0,
transition: {
duration: 1,
},
},
exit: (isBack: boolean) => ({
x: isBack ? 500 : -500,
opacity: 0,
scale: 0,
rotateX: 360,
transition: {
duration: 1,
},
}),
};
function App() {
const [visible, setVisible] = useState(1);
const [isBack, setIsBack] = useState(false);
const nextPlease = () => {
setIsBack(false);
setVisible((prev) => (prev === 10 ? 10 : prev + 1));
};
const prevPlease = () => {
setIsBack(true);
setVisible((prev) => (prev === 1 ? 1 : prev - 1));
};
return (
<Wrapper>
<AnimatePresence custom={isBack}>
<Box
custom={isBack}
variants={boxVariants}
initial="entry"
animate="center"
exit="exit"
key={visible}
>
{visible}
</Box>
</AnimatePresence>
<button onClick={prevPlease}>Prev</button>
<button onClick={nextPlease}>Next</button>
</Wrapper>
);
}
Framer Motion Docs
리액트 마스터클래스, 노마드코더