Commit fd19e5b6 authored by Ken's avatar Ken

feat: Add Lazy loading

parent 74b0cef4
......@@ -27,6 +27,7 @@
"query-string": "^7.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.4.1",
"react-redux": "^8.0.4",
"react-router-dom": "^6.4.5",
"react-scripts": "5.0.1",
......@@ -14496,6 +14497,14 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"node_modules/react-intersection-observer": {
"version": "9.4.1",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz",
"integrity": "sha512-IXpIsPe6BleFOEHKzKh5UjwRUaz/JYS0lT/HPsupWEQou2hDqjhLMStc5zyE3eQVT4Fk3FufM8Fw33qW1uyeiw==",
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
......
import { IPagination } from "pages/interface";
import axiosClient from "./axiosClient";
const newsApi = {
getNews: () => {
getNews: (params: IPagination) => {
const url = "/api/news";
return axiosClient.get(url);
return axiosClient.get(url, { params });
},
getNewsDetail: (id: string) => {
const url = `/api/news/${id}`;
......
......@@ -11,8 +11,6 @@ const NewsDetail = () => {
const { newsDetail } = useAppSelector(newsDetailSelector);
const { id } = useParams();
console.log(newsDetail);
useEffect(() => {
dispatch(handleLoading(true));
......@@ -38,7 +36,7 @@ const NewsDetail = () => {
<div
className="news-detail container py-4"
dangerouslySetInnerHTML={{
__html: purifyHTML(newsDetail.newspaperContent.content),
__html: purifyHTML(newsDetail.content),
}}
></div>
) : (
......
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import newsApi from "api/newsApi";
import { INewspaper } from "pages/interface";
import { INewspaper, IPagination } from "pages/interface";
const initialState: { newsData: INewspaper[] } = {
newsData: [],
};
export const getNews = createAsyncThunk("home/news", async () => {
const res = await newsApi.getNews();
return res;
});
export const getNews = createAsyncThunk(
"home/news",
async (params: IPagination) => {
const res = await newsApi.getNews(params);
return res;
}
);
const home = createSlice({
name: "home",
......@@ -17,13 +20,13 @@ const home = createSlice({
reducers: {},
extraReducers: (builder) => {
builder.addCase(getNews.fulfilled, (state, action: PayloadAction<any>) => {
const { data } = action.payload;
const sortedDataByDate = data.sort((a: INewspaper, b: INewspaper) => {
return (
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
});
state.newsData = sortedDataByDate;
const { collection } = action.payload.data;
// const sortedDataByDate = data.sort((a: INewspaper, b: INewspaper) => {
// return (
// new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
// );
// });
state.newsData = [...state.newsData, ...collection];
});
},
});
......
......@@ -2,30 +2,54 @@ import { handleLoading } from "app/globalSlice";
import { useAppDispatch, useAppSelector } from "app/hooks";
import { homeSelector } from "app/selectors";
import WrapperContainer from "components/WrapperContainer";
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import Newspaper from "../../components/Newspaper";
import { getNews } from "./homePageSlice";
import { Button } from "@mui/material";
import { IPagination } from "pages/interface";
import { useInView } from "react-intersection-observer";
import { CircularProgress } from "@mui/material";
const HomePage = () => {
const dispatch = useAppDispatch();
const { newsData } = useAppSelector(homeSelector);
const { ref, inView } = useInView({
threshold: 0.7,
initialInView: false,
delay: 100,
});
const [page, setPage] = useState<number>(1);
const [isLocalLoading, setIsLocalLoading] = useState<boolean>(false);
useEffect(() => {
dispatch(handleLoading(true));
try {
const fetchData = async () => {
await dispatch(getNews());
};
setIsLocalLoading(true);
const timeout = setTimeout(() => {
const newsParams: IPagination = {
Filters: "",
Sorts: "",
Page: page,
PageSize: 10,
};
const fetchData = async () => {
await dispatch(getNews(newsParams));
};
fetchData();
fetchData();
setIsLocalLoading(false);
}, 1000);
} catch (err) {
console.error("ERROR: ", err);
} finally {
dispatch(handleLoading(false));
setIsLocalLoading(false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [page]);
useEffect(() => {
if (inView) {
setPage((page) => page + 1);
}
}, [inView]);
return (
<main className="homePage">
......@@ -41,11 +65,14 @@ const HomePage = () => {
))}
</div>
<div className="homePage-load d-flex justify-content-center">
<Button variant="outlined" color="primary">
Xem Thêm
</Button>
</div>
{newsData.length > 0 && (
<div
className="homePage-load d-flex justify-content-center"
ref={ref}
>
{isLocalLoading && <CircularProgress />}
</div>
)}
</WrapperContainer>
</main>
);
......
......@@ -9,10 +9,12 @@ export interface INewspaper {
createdAt: string;
categorylink: string;
categorylinkNavigation: ICategory;
newspaperContent: INewspaperContent;
content: string;
}
export interface INewspaperContent {
id: string;
content: string;
export interface IPagination {
Filters: string;
Sorts: string;
PageSize: number;
Page: number;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment