AnimatePresence는 React js 앱에서 사라지는 컴포넌트를 animate한다.
AnimatePresence는 visible상태여야 한다.
그리고 그 children에는 조건문이 있어야 한다.
const Wrapper = styled(motion.div)`
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
`;
const Box = styled(motion.div)`
width: 400px;
height: 200px;
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
position: absolute;
top: 100px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;
const boxVariants = {
initial: {
opacity: 0,
scale: 0,
},
visible: {
opacity: 1,
scale: 1,
rotateZ: 360,
},
leaving: {
opacity: 0,
scale: 0,
y: 10,
},
};
function App() {
const [showing, setShowing] = useState(false);
const toggleShowing = () => setShowing((prev) => !prev);
return (
<Wrapper>
<button onClick={toggleShowing}>Click</button>
<AnimatePresence>
{showing ? (
<Box
variants={boxVariants}
initial="initial"
animate="visible"
exit="leaving"
/>
) : null}
</AnimatePresence>
</Wrapper>
);
}
export default App;
const Wrapper = styled(motion.div)`
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
`;
const Box = styled(motion.div)`
width: 400px;
height: 200px;
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
position: absolute;
top: 100px;
display: flex;
justify-content: center;
align-items: center;
font-size: 28px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;
const boxVariant = {
invisible: {
x: 500,
opacity: 0,
scale: 0,
},
visible: {
x: 0,
opacity: 1,
scale: 1,
transition: {
duration: 1,
},
},
exit: {
x: -500,
opacity: 0,
scale: 0,
transition: {
duration: 1,
},
},
};
function App() {
const [visible, setVisible] = useState(1);
const next = () => setVisible((prev) => (prev === 10 ? 1 : prev + 1));
return (
<Wrapper>
<AnimatePresence>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((i) =>
i === visible ? (
<Box
key={i}
variants={boxVariant}
initial="invisible"
animate="visible"
exit="exit"
>
{i}
</Box>
) : null
)}
</AnimatePresence>
<button onClick={next}>next</button>
</Wrapper>
);
}
export default App;
custom은 variants에 데이터를 보낼 수 있게 해주는 property이다.
custom을 사용하려면 variants를 함수로 바꿔야한다.
react js는 key속성을 보고 box가 unique하다고 판단하기 때문에 key를 바꾸면 이전 element가 사라지고 새 element가 생겼다고 판단한다. 이전 element가 사라졌다고 생각하기 때문에 exit animation이 발동한다.
exitBeforeEnter는 exit이 완전히 실행됐을 때만 다음 element를 불러오는 것이다. 저게 없으면 exit animation과 enter animation이 동시에 실행된다.
const Wrapper = styled(motion.div)`
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
`;
const Box = styled(motion.div)`
width: 400px;
height: 200px;
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
position: absolute;
top: 100px;
display: flex;
justify-content: center;
align-items: center;
font-size: 28px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;
const boxVariant = {
entry: (isBack: boolean) => {
return {
x: isBack ? -500 : 500,
opacity: 0,
scale: 0,
};
},
center: {
x: 0,
opacity: 1,
scale: 1,
transition: {
duration: 1,
},
},
exit: (isBack: boolean) => {
return {
x: isBack ? 500 : -500,
opacity: 0,
scale: 0,
transition: {
duration: 1,
},
};
},
};
function App() {
const [visible, setVisible] = useState(1);
const [back, setBack] = useState(false);
const nextB = () => {
setBack(false);
setVisible((prev) => (prev === 10 ? 1 : prev + 1));
};
const prevB = () => {
setBack(true);
setVisible((prev) => (prev === 1 ? 10 : prev - 1));
};
return (
<Wrapper>
<AnimatePresence custom={back}>
<Box
custom={back}
key={visible}
variants={boxVariant}
initial="entry"
animate="center"
exit="exit"
>
{visible}
</Box>
</AnimatePresence>
<button onClick={nextB}>next</button>
<button onClick={prevB}>prev</button>
</Wrapper>
);
}
export default App;