짱이 될거야
React 페이지 전환 애니메이션 본문
1. 라이브러리 설치
npm install react-transition-group
공식문서: https://reactcommunity.org/react-transition-group/
React Transition Group
Exposes simple components useful for defining entering and exiting transitions. React Transition Group is not an animation library like React-Motion, it does not animate styles by itself. Instead it exposes transition stages, manages classes and group elem
reactcommunity.org
2. CSSTransition, TransitionGroup
Transition, CSSTransition, SwitchTransition, TransitionGroup 중 CSSTransition과 TransitionGroup을 사용한다.
- CSSTransition: 애니메이션을 넣고자 하는 컴포넌트 윗 단에 불러오고, timeout(애니메이션 시간), classNames, onEnter 등을 적는다.
- classNames: 구성 요소에 적용되는 애니메이션 className. (appear, appearActive, appearDone, enter, enterActive, enterDone, exit, exitActive, exitDone) / styles.css 파일을 만들어서 사용한다.
- onEnter: 'enter' 또는 'appear' 클래스가 적용된 직후 발생하는 콜백.
- onEntering: 'enter-active' 또는 'appear-active' 클래스가 적용된 직후 발생하는 콜백.
- onEntered: 'enter' 또는 'appear' 클래스가 제거된 후 콜백.
- onExit: 'exit' 클래스가 적용된 직후 콜백 발생.
- onExiting: 'exit-active'가 적용된 직후 발생하는 콜백.
- onExited: 'exit' 클래스가 제거되고 콜백 발생.
- 참고: enter(마운트하기 시작할 때), enter-active(마운트 다했을 때), exit(언마운트 시작할 때), exit-active(언마운트 되고 난 후)
- TransitionGroup: Transition, CSSTransition을 관리.
3. import
import { TransitionGroup, CSSTransition } from "react-transition-group";
4. 시행착오
현재 프로젝트 폴더 구조는 다음과 같다.
- App.js
- Router.js
- index.js
index.js에서 App.js를 호출하고, App.js에서 Router.js를 호출한다.
Router.js는 아래 코드의 구조를 가지고 있다.
Router.js
import { BrowserRouter, Route, Routes } from "react-router-dom";
function Router() {
return (
<div>
<BrowerRouter>
<NavBar />
<Routes>
<Route>
</Route>
</Routes>
<Footer />
</BrowerRouter>
</div>
)
}
export default Router;
이 코드에 react-transition-group을 적용시켜 아래와 같이 만들었다.
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
import { TransitionGroup, CSSTransition } from "react-transition-group";
function Router() {
const location = useLocation();
return (
<div>
<BrowerRouter>
<NavBar />
<TransitionGroup>
<CSSTransition
key={location.pathname}
classNames="fade"
timeout={300}
>
<Routes location={location}>
<Route></Route>
</Routes>
</CSSTransition>
</TransitionGroup>
<Footer />
</BrowerRouter>
</div>
)
}
export default Router;
이 때, CSSTransition에는 key값이 필요하고, Routes에 location을 넘겨줘야 한다. location은 "react-router-dom"의 useLocation을 호출해서 쓰는데 이 부분에서 계속해서 에러가 났다.
현재 파일 위치에서 useLocation을 사용하면 안된다는 것 같았고, 구글링을 해봤다. 하지만 구글에 나온 코드들은 우리 프로젝트와 구조가 달랐는데, Router 안에서 App을 불러왔다.
그래서 다른 방법을 찾았고, 팀원의 조언을 바탕으로 TransitionGroup부터 Route 까지를 모아서 별도의 파일을 만든 후 import 시키기로 했다. 그 결과는 아래와 같다.
5. 결과
Router.js
import { BrowserRouter } from "react-router-dom";
import NavBar from "./components/Home/NavBar";
import Footer from "./components/Home/Footer";
import AnimationRouter from "./AnimationRouter";
function Router() {
return (
<div>
<BrowserRouter>
<NavBar />
<AnimationRouter />
<Footer />
</BrowserRouter>
</div>
);
}
export default Router;
AnimationRouter.js
import "./styles.css"
import { useEffect } from "react";
import { Route, Routes, useLocation } from "react-router-dom";
import { TransitionGroup, CSSTransition } from "react-transition-group";
function AnimationRouter () {
const location = useLocation();
return (
<TransitionGroup>
<CSSTransition
key={location.pathname}
classNames="fade"
timeout={300}
>
<Routes location={location}>
<Route></Route>
...
</Routes>
</CSSTransition>
</TransitionGroup>
)
}
export default AnimationRouter;
styles.css
.fade-enter {
opacity: 0.3;
}
.fade-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0.3;
transition: opacity 500ms ease-in;
}
6. 마무리
라우터 페이지에 애니메이션을 적용시키는 것은 생각보다 어렵지 않았다.
하지만 아직 react 사용법을 완전히 익히지 못해서 useLocation을 사용할 수 있는 파일 위치 등에서 오랜 시간이 걸렸다.
className이 아니라 classNames로 css를 사용하는 것과 enter, enter-active, exit, exit-active 등으로 나눠서 css를 줄 수 있다는 것이 새로웠다.
이제 애니메이션을 주는 데에는 성공했으니까 css를 조금 더 수정해봐야겠다.
'프로젝트' 카테고리의 다른 글
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body. (0) | 2022.09.27 |
---|---|
Vuex 페이지 렌더링 전 data 호출(undefined) 문제해결 (0) | 2022.09.24 |
React 프로젝트, GitHub으로 배포하기 (0) | 2022.08.24 |
React 채팅방 css (0) | 2022.08.17 |
Firebase Web: URL로 이미지 다운로드하기 (0) | 2022.08.12 |