인프런 워밍업 클럽 스터디 1기 FE 과제(9번 과제)

인프런 워밍업 클럽 스터디 1기 FE 과제(9번 과제)

[9번 과제(Day10) - 디즈니 플러스 앱]

따라하며 배우는 리액트 A-Z

학습 범위: Section 4 ~ 5

https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/disney-plus-app

과제 이미지

image- 구글 로그인, swiper, 모달

image- 유튜브 플레이, 검색, 상세페이지, 로그아웃


  • 고민한 것

    • MovieModal mount될 때에는 애니메이션이 되고, unmount될 때에는 애니메이션 없이 툭 사라져버린다.

    • 내가 원하는 것은 모달이 꺼질때에도 애니메이션으로 사라지게 한 후, unmount되게 하는 것

    • 기존 코드

      // Row 컴포넌트 
      modalOpen && <MovieModal {...movieSelection} setModalOpen={setModalOpen} />

      이전 코드에서는 modalOpen 상태가 참일 때만 MovieModal이 렌더링되었지만, 변경된 코드에서는 MovieModal 컴포넌트 내부에서 직접적으로 modalOpen 상태를 조작할 수 있도록 했다.

    • 변경 코드

       

      // Row 컴포넌트
      <MovieModal {...movieSelection} modalOpen={modalOpen} setModalOpen={setModalOpen} />
      
      // MovieModal 컴포넌트
      const MovieModal = ({
        ...
        modalOpen,
        setModalOpen,
      }) => {
        const ref = useRef();
        const [showModal, setShowModal] = useState(false);
        const [animation, setAnimation] = useState("");
      
        useOnClickOutside(ref, () => {
          // 2. 닫기 이벤트
          setModalOpen(false);
        });
      
        useEffect(() => {
          if (!modalOpen) {
            // 4. 사라지는 애니메이션으로 설정
            setAnimation("animate-fade-down animate-reverse");
          } else {
            setShowModal(true);
            setTimeout(() => {
              // 1. 나타나는 애니메이션으로 설정
              setAnimation("animate-fade-up");
            }, 10);
          }
        }, [modalOpen]);
      
        return (
          showModal && (
            <div className="animate-fade">
              <article
                className={`${animation}`}
                ref={ref}
                onAnimationEnd={() => {
                  // 3. 사라지는 애니메이션 끝이나면 showModal false
                  if (!modalOpen) setShowModal(false);
                }}
              ></article>
            </div>
          )
        )
      };
      • MovieModal 컴포넌트 내부에서는 modalOpen 상태에 따라 모달의 나타남과 사라짐을 제어하는 useEffect와 useState를 사용했다.

      • modalOpen 상태가 변경될 때마다 useEffect가 실행되어 애니메이션 클래스를 설정하고, 애니메이션 효과를 주는 CSS 클래스를 적용시킨다.

      • onAnimationEnd 이벤트 핸들러를 사용하여 애니메이션 종료 후에 showModal 상태를 변경하여 모달이 화면에서 완전히 사라지도록 처리했다.

       

  • 추가한 것

    • tailwind css + 스크롤바 숨기는 플러그인, 애니메이션 플러그인

      /** @type {import('tailwindcss').Config} */
      module.exports = {
        content: ["./src/**/*.{js,jsx,ts,tsx}"],
        theme: {
          extend: {},
        },
        plugins: [
          require("tailwind-scrollbar-hide"),
          require("tailwindcss-animated"),
        ],
      };
    • 회원만 접근 가능한 parent 컴포넌트 생성

      const UserGuard = () => {
        const navigate = useNavigate();
        useEffect(() => {
          const profilePictureUrl = localStorage.getItem("profilePictureUrl");
          // 로그인 시 저장한 구글 유저 프로필이미지가 없다면 LandingPage로 이동
          if (!profilePictureUrl) {
            navigate("/");
          }
        }, [navigate]);
        return <Outlet />;
      };
      
      export default UserGuard;
      
      function App() {
        return (
          <div className="App">
            <Routes>
              <Route path="/" element={<Layout />}>
                <Route index element={<LandingPage />} />
                👇
                <Route element={<UserGuard />}>
                  <Route path="main" element={<MainPage />} />
                  <Route path=":movieId" element={<DetailPage />} />
                  <Route path="search" element={<SearchPage />} />
                </Route>
              </Route>
            </Routes>
          </div>
        );
      }
      
      export default App;
    • 로그인 상태일 때 랜딩 페이지 접근 불가

      const LandingPage = () => {
        const navigate = useNavigate();
        useEffect(() => {
          const profilePictureUrl = localStorage.getItem("profilePictureUrl");
          // 로그인 시 저장한 구글 유저 프로필이미지가 있다면 MainPage로 이동
          if (profilePictureUrl) {
            navigate("/main");
          }
        }, [navigate]);
      
        return (...)
      };

댓글을 작성해보세요.

채널톡 아이콘