로딩

이시원·2022년 9월 16일
0
post-thumbnail

npm install --save react-spinners
import ClipLoader from "react-spinners/ClipLoader";

  • 개요

    • loading이 true면 loading 스피너를 보여준다
    • loading이 false면 데이터를 보여준다
    • true : 데이터 도착 전
    • false : 데이터 도착 후 or 에러가 났을 때
// movieAction.js
import api from "../api";
import { movieActions } from "../reducers/movieReducer";

const API_KEY = process.env.REACT_APP_API_KEY;
function getMovies() {
  return async (dispatch) => {
    try {
      // 데이터 도착 전
      dispatch(movieActions.handleLoding());
      
      const popularMovieApi = api.get(
        `/movie/popular?api_key=${API_KEY}&language=en-US&page=1`
      );

      const topRatedApi = api.get(
        `/movie/top_rated?api_key=${API_KEY}&language=en-US&page=1`
      );

      const upComingApi = api.get(
        `/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`
      );

      let [popularMovies, topRatedMovies, upComingMovies] = await Promise.all([
        popularMovieApi,
        topRatedApi,
        upComingApi,
      ]);

      dispatch(
        movieActions.getMovies({
          popularMovies: popularMovies.data,
          topRatedMovies: topRatedMovies.data,
          upComingMovies: upComingMovies.data,
        })
      );
    } catch (error) {
      // 에러 핸들링 하는 곳
      dispatch(movieActions.failMovies());
    }
  };
}

export const movieAction = { getMovies };
// movieReducer.js
import { createSlice } from "@reduxjs/toolkit";

let initialState = {
  popularMovies: {},
  topRatedMovies: {},
  upcomingMovies: {},
  loading: true,
};

const movieSlice = createSlice({
  name: "movie",
  initialState,
  reducers: {
    // 데이터 도착 전
    handleLoding(state, action) {
      state.loading = true;
    },
    getMovies(state, action) {
      state.popularMovies = action.payload.popularMovies;
      state.topRatedMovies = action.payload.topRatedMovies;
      state.upComingMovies = action.payload.upComingMovies;
      // 데이터 도착 후
      state.loading = false;
    },
    // 에러가 났을 때
    failMovies(state, action) {
      state.loading = false;
    },
  },
});

export const movieActions = movieSlice.actions;
export default movieSlice.reducer;
// Home.js
import React, { useEffect } from "react";
import { movieAction } from "../redux/actions/movieAction";
import { useDispatch, useSelector } from "react-redux/es/exports";
import Banner from "../components/Banner";
import MovieSlide from "../components/MovieSlide";
import ClipLoader from "react-spinners/ClipLoader";

const Home = () => {
  const dispatch = useDispatch();
  const { popularMovies, topRatedMovies, upComingMovies, loading } =
    useSelector((state) => state.movie);

  useEffect(() => {
    dispatch(movieAction.getMovies());
  }, []);
  
  if (loading) {
    return (
      <div className="loading">
        <ClipLoader color="#ffff" loading={loading} size={150} />
      </div>
    );
  }
  return (
    <div>
      {/* 로딩스피너를 만들었으면 조건부 렌더링을 지워도 된다. */}
      <Banner movie={popularMovies.results[0]} />
      <h1>Popular Movie</h1>
      <MovieSlide movies={popularMovies} />
      <h1>Top Rated Movie</h1>
      <MovieSlide movies={topRatedMovies} />
      <h1>UpComing Movie</h1>
      <MovieSlide movies={upComingMovies} />
    </div>
  );
};

export default Home;
profile
코딩공부

0개의 댓글