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;
LoadingIndicator.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;
LoadingIndicator.scss
.loading {
display: flex;
justify-content: space-between;
align-self: center;
width: 480px;
&__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;
&:nth-child(1) {
animation: move-1 2s infinite;
}
&: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);
}
}
Hi all.I try to show <LoadingIndicator />
component when moviesStatus === "loading"
until moviesStatus === "succeeded"
but issue is <LoadingIndicator />
component appears but doesnt move as you can see in demo(three big blue balls).I literally do the same things in this documentation(https://codesandbox.io/s/github/reduxjs/redux-essentials-example-app/tree/checkpoint-3-postRequests/?from-embed=&file=/src/features/posts/PostsList.js) but doesnt work.I haven't been able to solve the problem for days.
demo : https://hope-movie.web.app/page/1 repo : https://github.com/UmutPalabiyik/hope-movie-app
You got response from server very quickly, so you can not see LoadingIndicator. To see LoadingIndicator you can make getting response slower manually. You can update you fetchMovies
function like this:
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);
});
});