From 719049a15f8b15ffc657c46e8cefb65d1e9f4e98 Mon Sep 17 00:00:00 2001 From: YHhaoareyou Date: Thu, 7 Sep 2023 01:39:44 +0900 Subject: [PATCH] feat: infinite scroll to load more threads --- apps/forum/package.json | 1 + apps/forum/pnpm-lock.yaml | 17 ++++++ apps/forum/src/components/App.tsx | 8 +-- apps/forum/src/components/Board.tsx | 88 +++++++++++++++++++++------- apps/forum/src/components/Thread.tsx | 1 - 5 files changed, 88 insertions(+), 27 deletions(-) diff --git a/apps/forum/package.json b/apps/forum/package.json index 2c40e47df..157a56145 100644 --- a/apps/forum/package.json +++ b/apps/forum/package.json @@ -68,6 +68,7 @@ "react-ga": "3.3.0", "react-helmet": "6.1.0", "react-i18next": "11.15.6", + "react-infinite-scroll-component": "^6.1.0", "react-responsive": "9.0.0-beta.10", "react-router-dom": "^6.11.2", "recoil": "^0.7.7", diff --git a/apps/forum/pnpm-lock.yaml b/apps/forum/pnpm-lock.yaml index b49e036f4..17778858e 100644 --- a/apps/forum/pnpm-lock.yaml +++ b/apps/forum/pnpm-lock.yaml @@ -68,6 +68,9 @@ dependencies: react-i18next: specifier: 11.15.6 version: 11.15.6(i18next@19.9.2)(react-dom@17.0.2)(react-native@0.68.7)(react@17.0.2) + react-infinite-scroll-component: + specifier: ^6.1.0 + version: 6.1.0(react@17.0.2) react-responsive: specifier: 9.0.0-beta.10 version: 9.0.0-beta.10(react@17.0.2) @@ -7327,6 +7330,15 @@ packages: react-native: 0.68.7(@babel/core@7.17.5)(@babel/preset-env@7.16.11)(react@17.0.2) dev: false + /react-infinite-scroll-component@6.1.0(react@17.0.2): + resolution: {integrity: sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==} + peerDependencies: + react: '>=16.0.0' + dependencies: + react: 17.0.2 + throttle-debounce: 2.3.0 + dev: false + /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -8184,6 +8196,11 @@ packages: /throat@5.0.0: resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + /throttle-debounce@2.3.0: + resolution: {integrity: sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==} + engines: {node: '>=8'} + dev: false + /through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} dependencies: diff --git a/apps/forum/src/components/App.tsx b/apps/forum/src/components/App.tsx index 81c842585..638b5445f 100644 --- a/apps/forum/src/components/App.tsx +++ b/apps/forum/src/components/App.tsx @@ -15,9 +15,9 @@ const App = () => { const { theme, setTheme } = React.useContext(ThemeContext); return ( -
+
-
+
{ changeLang={(lng: string | undefined) => i18n.changeLanguage(lng)} />
-
+
{/*
*/} @@ -38,7 +38,7 @@ const App = () => {
{/*
*/} -
+
diff --git a/apps/forum/src/components/Board.tsx b/apps/forum/src/components/Board.tsx index aaff35b6a..ddc4999b7 100644 --- a/apps/forum/src/components/Board.tsx +++ b/apps/forum/src/components/Board.tsx @@ -9,6 +9,10 @@ import { currentGroupsState, currentTagsState } from "@app/recoil/atoms"; import { filterThreadsByTags, filterThreadsByGroups } from "@app/utils/filter"; import { API } from "@aws-amplify/api"; import Thread from "@app/types/thread"; +import { getUserAttr } from "wasedatime-ui"; +import InfiniteScroll from "react-infinite-scroll-component"; + +const threadCountPerPage = 3; // 10 const Board = () => { const { boardSlug } = useParams(); @@ -20,8 +24,10 @@ const Board = () => { boards.find((board) => board.slug === boardSlug)?.slug || "academic" ); - const [boardThreads, setBoardThreads] = useState([]); + const [boardThreads, setBoardThreads] = useState([]); const [filteredThreads, setFilteredThreads] = useState([]); + const [userToken, setUserToken] = useState(""); + const [page, setPage] = useState(1); const boardStorage = localForage.createInstance({ name: "BoardData", @@ -32,49 +38,87 @@ const Board = () => { var currentBoardId = boards.find((board) => board.slug === boardSlug)?.slug || "academic"; setBoardId(currentBoardId); + getThreads(currentBoardId); + }, [boardSlug]); - API.get("wasedatime-dev", `/forum/${currentBoardId}`, { + const getThreads = async (boardId: string) => { + let userId = userToken; + if (userId.length == 0) { + const userAttr = await getUserAttr(); + if (userAttr) { + userId = userAttr.id; + setUserToken(userId); + } + } + + API.get("wasedatime-dev", `/forum/${boardId}?uid=${userId}`, { headers: { "Content-Type": "application/json", }, response: true, }) .then((res) => { - console.log(res.data.data); var threads = res.data.data.filter( - (thread: Thread) => thread.board_id === currentBoardId + (thread: Thread) => thread.board_id === boardId ); - - threads = filterThreadsByTags(threads, currentTags); - threads = filterThreadsByGroups(threads, currentGroups); - setFilteredThreads(threads); setBoardThreads(threads); - boardStorage.setItem(currentBoardId, threads); + var filteredThreads = filterThreadsByTags(threads, currentTags); + filteredThreads = filterThreadsByGroups(filteredThreads, currentGroups); + if (filteredThreads.length > threadCountPerPage * page) filteredThreads = filteredThreads.slice(0, threadCountPerPage * page); + setFilteredThreads(filteredThreads); + + boardStorage.setItem(boardId, threads); }) .catch((e) => { console.error(e); }); - }, [boardSlug]); + }; - // when currentTags change, filter the threads + // when currentTags or currentGroups change, filter the threads useEffect(() => { - var threads = filterThreadsByTags(boardThreads, currentTags); - setFilteredThreads(threads); - }, [currentTags, boardThreads]); + var filteredThreads = filterThreadsByTags(boardThreads, currentTags); + filteredThreads = filterThreadsByGroups(filteredThreads, currentGroups); + if (filteredThreads.length > threadCountPerPage * page) filteredThreads = filteredThreads.slice(0, threadCountPerPage * page); + if (filteredThreads.length > threadCountPerPage * page) filteredThreads = filteredThreads.slice(0, threadCountPerPage * page); + setFilteredThreads(filteredThreads); + }, [currentTags, currentGroups]); - // when currentGroups change, filter the threads - useEffect(() => { - var threads = filterThreadsByGroups(boardThreads, currentGroups); - setFilteredThreads(threads); - }, [currentGroups, boardThreads]); + const displayMoreThread = () => { + setTimeout(() => { + if (boardThreads.length < threadCountPerPage * page) return; + const nextPage = page + 1; + setPage(nextPage); + var threads = filterThreadsByTags(boardThreads, currentTags); + threads = filterThreadsByGroups(threads, currentGroups); + threads = threads.slice(0, threadCountPerPage * nextPage); + setFilteredThreads(threads); + }, 1000); + + } return (
- {filteredThreads.map((thread, i) => ( - - ))} +
+ Loading...} + style={{ overflowY: "hidden" }} + > + {/* {this.state.items.map((i, index) => ( +
+ div - #{index} +
+ ))} */} + {filteredThreads.map((thread, i) => ( + + ))} +
+
); }; diff --git a/apps/forum/src/components/Thread.tsx b/apps/forum/src/components/Thread.tsx index af9c4a6bd..ffd774e1f 100644 --- a/apps/forum/src/components/Thread.tsx +++ b/apps/forum/src/components/Thread.tsx @@ -20,7 +20,6 @@ const Thread = () => { console.log("could not find user Id"); } else { let userId = userAttr.id; - console.log(userId); setUserToken(userId); fetchData(userId); }