Индикатор загрузки появляется, но не перемещается в react-redux

#javascript #reactjs #redux-thunk #redux-toolkit

Вопрос:

 import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { BiLeftArrow, BiRightArrow } from "react-icons/bi";
import { useHistory } from "react-router-dom";

import {
  fetchMovies,
  handleCurrentPage,
  handleStatus,
} from "../../feautures/movies/moviesSlice";
import Card from "../Card/Card";
import Slider from "../UI/Slider/Slider";
import Navigation from "../Navigations/Navigation";

import "./MoviesList.scss";
import requests from "../../requests";
import LoadingIndicator from "../UI/LoadingIndicator/LoadingIndicator";

const MoviesList = () => {
  const dispatch = useDispatch();

  // Handle movies states
  const moviesStatus = useSelector((state) => state.movies.status);
  const moviesState = useSelector((state) => state.movies.movies);
  const moviesError = useSelector((state) => state.movies.error);
  const moviesHeading = useSelector((state) => state.movies.moviesHeading); // It's for pagination
  const moviesCurrentPage = useSelector((state) => state.movies.currentPage);

  let history = useHistory();

  // Handle header input
  const inputValue = useSelector((state) => state.movies.inputValue);

  // Movies according input values
  const filteredMovie = moviesState.filter((movie) =>
    movie.original_title.toLowerCase().includes(inputValue)
  );

  // Handle page number
  const handlePageNumber = (nexPage) => {
    dispatch(handleStatus("idle"));
    dispatch(
      handleCurrentPage(Math.max(1, Math.min(moviesCurrentPage   nexPage, 10)))
    );
  };

  // Handle pagination
  useEffect(() => {
    if (moviesStatus === "idle") {
      if (moviesHeading === "POPULAR") {
        dispatch(fetchMovies(requests.fetchPopular(moviesCurrentPage)));
      } else if (moviesHeading === "NOW PLAYING") {
        dispatch(fetchMovies(requests.fetchNowPlaying(moviesCurrentPage)));
      } else if (moviesHeading === "UP COMING") {
        dispatch(fetchMovies(requests.fetchUpComing(moviesCurrentPage)));
      }
    }
  }, [moviesCurrentPage, dispatch, moviesHeading, moviesStatus]);

  let content;

  if (moviesStatus === "loading") {
  } else if (moviesStatus === "succeeded") {
    content = (
      <div className="movies__container">
        <BiLeftArrow
          className="movies__arrow movies__arrow--left"
          onClick={() => {
            handlePageNumber(-1);
            history.push(
              `/page/${(() =>
                Math.max(1, Math.min(moviesCurrentPage - 1, 10)))()}`
            );
          }}
        />
        {filteredMovie.map((movie) => {
          return <Card movie={movie} key={movie.id} />;
        })}
        <BiRightArrow
          className="movies__arrow movies__arrow--right"
          onClick={() => {
            handlePageNumber(1);
            history.push(
              `/page/${(() =>
                Math.max(1, Math.min(moviesCurrentPage   1, 10)))()}`
            );
          }}
        />
      </div>
    );
  } else if (moviesStatus === "failed") {
    content = <div>{moviesError}</div>;
  }

  return (
    <div className="movies">
      <Slider />
      <Navigation />
      {moviesStatus === "loading" ? <LoadingIndicator /> : content}
    </div>
  );
};

export default MoviesList;
 

Индикатор загрузки.jsx

 import "./LoadingIndicator.scss"

const LoadingIndicator = () => {
  return (
    <div className="loading">
      <div className="loading__circle"></div>
      <div className="loading__circle"></div>
      <div className="loading__circle"></div>
    </div>
  );
};

export default LoadingIndicator;
 

Индикатор загрузки.scss

 .loading {
  display: flex;
  justify-content: space-between;
  align-self: center;
  
  width: 480px;
  amp;__circle {
    width: 150px;
    height: 150px;
    border-radius: 50%;
    background: linear-gradient(
      45deg,
      rgba(2, 0, 36, 1) 0%,
      rgba(9, 9, 121, 1) 35%,
      rgba(0, 212, 255, 1) 100%
    );
    box-shadow: inset 0 0 0 5px rgba(255, 255, 255, 0.3);
    transform: translateX(0);
    z-index: 2;
    amp;:nth-child(1) {
      animation: move-1 2s infinite;
    }
    amp;:nth-child(3) {
      animation: move-3 2s infinite;
    }
  }
}
@keyframes move-1 {
  0% {
    z-index: 3;
    transform: translateX(0);
  }
  25% {
    z-index: 3;
    transform: translateX(80px);
  }
  50% {
    z-index: 3;
    transform: translateX(0);
  }

  50.1% {
    z-index: 1;
    transform: translateX(0);
  }
  75% {
    z-index: 1;
    transform: translateX(80px);
  }
  100% {
    z-index: 1;
    transform: translateX(0);
  }
}
@keyframes move-3 {
  0% {
    z-index: 1;
    transform: translateX(0);
  }
  25% {
    z-index: 1;
    transform: translateX(-80px);
  }
  50% {
    z-index: 1;
    transform: translateX(0);
  }

  50.1% {
    z-index: 3;
    transform: translateX(0);
  }
  75% {
    z-index: 3;
    transform: translateX(-80px);
  }
  100% {
    z-index: 3;
    transform: translateX(0);
  }
}
 
 

Привет всем.Я пытаюсь показать <LoadingIndicator /> компонент, когда moviesStatus === "loading" пока moviesStatus === "succeeded" , но проблема <LoadingIndicator /> в том, что компонент появляется, но не движется, как вы можете видеть в демо(три больших синих шара).Я буквально делаю то же самое в этом documentation(https://codesandbox.io/s/github/reduxjs/redux-essentials-example-app/tree/checkpoint-3-postRequests/?from-embed=amp;file=/src/features/posts/PostsList.js) но не работает.Я уже несколько дней не мог решить эту проблему.

ДЕМОНСТРАЦИЯ : https://hope-movie.web.app/page/1 репо : https://github.com/UmutPalabiyik/hope-movie-app

Комментарии:

1. Можете ли вы предоставить код css <LoadingIndicator /> ?

2. Я добавил, но я не думаю, что это связано с этим, потому что компонент <LoadingIndicator /> работает должным образом где-то в другом месте.

Ответ №1:

Вы получили ответ от сервера очень быстро, поэтому вы не можете видеть индикатор загрузки. Чтобы увидеть индикатор загрузки, вы можете вручную замедлить получение ответа. Вы можете обновить fetchMovies свою функцию следующим образом:

 export const fetchMovies = createAsyncThunk("movies/fetch", async (arg) => {
  return await new Promise((resolve) => {
    setTimeout(async () => {
      console.log("url: ", arg);
      const response = await axios.get(arg);
      resolve(response.data.results);
    }, 3000);
  });
});