From b925932ba05f5c31e2cf4c14cf9d9e7c87d7456c Mon Sep 17 00:00:00 2001 From: zhanglun Date: Thu, 30 Nov 2023 17:59:02 +0800 Subject: [PATCH] fix: state update render --- src/layout/Search/Result.tsx | 60 ++++++----------- src/layout/Search/hooks.tsx | 127 ----------------------------------- src/layout/Search/index.tsx | 126 +++++++++++++++++++++++++++++++--- 3 files changed, 139 insertions(+), 174 deletions(-) delete mode 100644 src/layout/Search/hooks.tsx diff --git a/src/layout/Search/Result.tsx b/src/layout/Search/Result.tsx index fb8155eb3..3d7f32050 100644 --- a/src/layout/Search/Result.tsx +++ b/src/layout/Search/Result.tsx @@ -1,25 +1,24 @@ import { ArticleResItem } from "@/db"; import { ResultItem } from "./ResultItem"; import { ArticleDialogView } from "@/components/ArticleView/DialogView"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useBearStore } from "@/stores"; -import { useSearchListHook } from "./hooks"; import clsx from "clsx"; import { Skeleton } from "@/components/ui/skeleton"; export interface SearchResultProps extends React.HTMLAttributes { query: string; + resultList: ArticleResItem[]; } + export function SearchResult(props: SearchResultProps) { - const { className } = props; + const { className, resultList } = props; const store = useBearStore((state) => ({ articleDialogViewStatus: state.articleDialogViewStatus, setArticleDialogViewStatus: state.setArticleDialogViewStatus, })); - const { resultList, listRef, loadRef, loading, observerTarget } = useSearchListHook(); - console.log("%c Line:21 🍓 articleList", "color:#465975", resultList); - const [currentArticle, setCurrentArticle] = useState( + const [ currentArticle, setCurrentArticle ] = useState( null ); @@ -31,51 +30,34 @@ export function SearchResult(props: SearchResultProps) { function renderResultList(list: ArticleResItem[]) { return (
- {list.map((article) => { + { list.map((article) => { return ( ); - })} + }) }
); } return ( -
-
- {renderResultList(resultList)} -
- {loading && ( -
- -
- -
-
- -
-
- -
-
- )} -
-
2
+ <> +
+ { renderResultList(resultList) }
- {}} - afterCancel={() => { + article={ currentArticle } + dialogStatus={ store.articleDialogViewStatus } + setDialogStatus={ store.setArticleDialogViewStatus } + afterConfirm={ () => { + } } + afterCancel={ () => { setCurrentArticle(null); - }} + } } /> -
+ ); } diff --git a/src/layout/Search/hooks.tsx b/src/layout/Search/hooks.tsx deleted file mode 100644 index bf9e52f34..000000000 --- a/src/layout/Search/hooks.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { useCallback, useEffect, useRef, useState } from "react"; -import { useHotkeys } from "react-hotkeys-hook"; -import { useBearStore } from "@/stores"; -import { throttle } from "lodash"; -import { request } from "@/helpers/request"; -import { AxiosResponse } from "axios"; -import { ArticleResItem } from "@/db"; - -export interface SearchParams { - query: string; -} - -export const useSearchListHook = () => { - const [query, setQuery] = useState(""); - const [loading, setLoading] = useState(false); - const [hasMore, setHasMore] = useState(true); - const [resultList, setResultList] = useState([]); - const [cursor, setCursor] = useState(1); - const listRef = useRef(null); - const loadRef = useRef(null); - const observerTarget = useRef(null); - - const getList = (params: { query?: string; cursor?: number }) => { - setLoading(true); - console.log("%c Line:26 🍇 query", "color:#fca650", query); - console.log("%c Line:38 🍆 cursor", "color:#93c0a4", cursor); - console.log("%c Line:37 🌽 params.cursor", "color:#ffdd4d", params.cursor); - - if (!query) { - return; - } - - request - .get("/search", { - params: { - query: query, - cursor: params.cursor || cursor, - }, - }) - .then((res: AxiosResponse) => { - const list = res.data; - - console.log("%c Line:43 🍞 list", "color:#42b983", list); - - setResultList((prev) => [...prev, ...list]); - console.log("%c Line:46 🥪 [...prev, ...list]", "color:#4fff4B", [...list]); - setCursor((prev) => prev + 1); - - if (list.length === 0) { - setHasMore(false); - } - }) - .finally(() => { - setLoading(false); - }) - .catch((err: any) => { - console.log("%c Line:71 🍎 err", "color:#ffdd4d", err); - }); - }; - - useEffect(() => { - if (query) { - setResultList([]); - setCursor(1); - setHasMore(true); - getList({ query, cursor: 1 }); - } - }, [query]); - - useEffect(() => { - const observer = new IntersectionObserver( - (entries) => { - console.log( - "%c Line:74 🍔 entries[0].isIntersecting", - "color:#fca650", - entries[0].isIntersecting - ); - if (entries[0].isIntersecting) { - getList({}); - } - }, - { threshold: 1 } - ); - - if (observerTarget.current) { - observer.observe(observerTarget.current); - } - - return () => { - if (observerTarget.current) { - observer.unobserve(observerTarget.current); - } - }; - }, [observerTarget]); - - const goPrev = useCallback( - throttle(() => { - console.warn("goPrev"); - // store.goPreviousArticle(); - }, 300), - [] - ); - - const goNext = useCallback( - throttle(() => { - console.warn("goNext"); - // store.goNextArticle(); - }, 300), - [] - ); - - useHotkeys("n", goNext); - useHotkeys("Shift+n", goPrev); - - return { - query, - setQuery, - getList, - loading, - hasMore, - resultList, - setLoading, - listRef, - loadRef, - observerTarget, - }; -}; diff --git a/src/layout/Search/index.tsx b/src/layout/Search/index.tsx index 10df0a8ba..eb9295d37 100644 --- a/src/layout/Search/index.tsx +++ b/src/layout/Search/index.tsx @@ -1,35 +1,145 @@ -import { useCallback, useEffect, useState } from "react"; -import { debounce } from "lodash"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { debounce, throttle } from "lodash"; import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import { SearchResult } from "./Result"; -import { useSearchListHook } from "./hooks"; +import { ArticleResItem } from "@/db"; +import { request } from "@/helpers/request"; +import { AxiosResponse } from "axios"; +import { useHotkeys } from "react-hotkeys-hook"; +import { Skeleton } from "@/components/ui/skeleton"; +import clsx from "clsx"; export const SearchPage = () => { - const { query, setQuery } = useSearchListHook(); + const [query, setQuery] = useState(""); + const [loading, setLoading] = useState(false); + const [hasMore, setHasMore] = useState(true); + const [resultList, setResultList] = useState([]); + const [cursor, setCursor] = useState(1); + const loadRef = useRef(null); + const observerTarget = useRef(null); + const debounceSearch = useCallback( debounce((query: string) => { - setQuery(query); + setResultList([]); + + getList({ query, cursor: 1 }); }, 200), [] ); const handleSearch = (e: React.ChangeEvent) => { const val = e.target.value as string; + setQuery(val); + console.log("%c Line:35 🥔 val", "color:#33a5ff", val); val && debounceSearch(val); }; + const getList = useCallback((params: any) => { + setLoading(true); + const text = params.query || query; + console.log("%c Line:41 🍕 query", "color:#ed9ec7", query); + + if (!text) { + return; + } + + request + .get("/search", { + params: { + query: text.trim(), + cursor: params.cursor || cursor, + }, + }) + .then((res: AxiosResponse) => { + const list = res.data; + + setResultList((prevState) => [...prevState, ...list]); + setCursor(cursor + 1); + + if (list.length === 0) { + setHasMore(false); + } + }) + .finally(() => { + setLoading(false); + }) + .catch((err: any) => { + console.log("%c Line:71 🍎 err", "color:#ffdd4d", err); + }); + }, [query, cursor]); + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + console.log(entries[0].isIntersecting); + if (entries[0].isIntersecting) { + getList({}); + } + }, + { threshold: 1 } + ); + + if (observerTarget.current) { + observer.observe(observerTarget.current); + } + + return () => { + if (observerTarget.current) { + observer.unobserve(observerTarget.current); + } + }; + }, [observerTarget]); + + const goPrev = useCallback( + throttle(() => { + console.warn("goPrev"); + // store.goPreviousArticle(); + }, 300), + [] + ); + + const goNext = useCallback( + throttle(() => { + console.warn("goNext"); + // store.goNextArticle(); + }, 300), + [] + ); + + useHotkeys("n", goNext); + useHotkeys("Shift+n", goPrev); + return (
- -
- +

Query: {query}

+
+ +
+ {loading ? "laoding" : ""} + {loading && ( +
+ +
+ +
+
+ +
+
+ +
+
+ )} +
+
2
+
); };