Skip to content

Commit

Permalink
fix: state update render
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanglun committed Nov 30, 2023
1 parent 985086b commit b925932
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 174 deletions.
60 changes: 21 additions & 39 deletions src/layout/Search/Result.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLDivElement> {
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<ArticleResItem | null>(
const [ currentArticle, setCurrentArticle ] = useState<ArticleResItem | null>(
null
);

Expand All @@ -31,51 +30,34 @@ export function SearchResult(props: SearchResultProps) {
function renderResultList(list: ArticleResItem[]) {
return (
<div>
{list.map((article) => {
{ list.map((article) => {
return (
<ResultItem
key={article.uuid}
article={article}
onView={handelViewResultItem}
key={ article.uuid }
article={ article }
onView={ handelViewResultItem }
/>
);
})}
}) }
</div>
);
}

return (
<div className={clsx("overflow-auto", className)}>
<div className="max-w-[840px] m-auto" ref={listRef}>
{renderResultList(resultList)}
<div ref={loadRef}>
{loading && (
<div className="p-3 pl-6 grid gap-1 relative">
<Skeleton className="h-5 w-full" />
<div>
<Skeleton className="h-3 w-full" />
</div>
<div>
<Skeleton className="h-3 w-full m-[-2px]" />
</div>
<div>
<Skeleton className="h-3 w-32" />
</div>
</div>
)}
</div>
<div ref={observerTarget}>2</div>
<>
<div className="max-w-[840px] m-auto">
{ renderResultList(resultList) }
</div>

<ArticleDialogView
article={currentArticle}
dialogStatus={store.articleDialogViewStatus}
setDialogStatus={store.setArticleDialogViewStatus}
afterConfirm={() => {}}
afterCancel={() => {
article={ currentArticle }
dialogStatus={ store.articleDialogViewStatus }
setDialogStatus={ store.setArticleDialogViewStatus }
afterConfirm={ () => {
} }
afterCancel={ () => {
setCurrentArticle(null);
}}
} }
/>
</div>
</>
);
}
127 changes: 0 additions & 127 deletions src/layout/Search/hooks.tsx

This file was deleted.

126 changes: 118 additions & 8 deletions src/layout/Search/index.tsx
Original file line number Diff line number Diff line change
@@ -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<ArticleResItem[]>([]);
const [cursor, setCursor] = useState(1);
const loadRef = useRef<HTMLDivElement>(null);
const observerTarget = useRef<HTMLDivElement>(null);

const debounceSearch = useCallback(
debounce((query: string) => {
setQuery(query);
setResultList([]);

getList({ query, cursor: 1 });
}, 200),
[]
);

const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
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<ArticleResItem[]>) => {
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 (
<div className="h-[100vh] flex flex-col">
<div className="p-4 bg-background">
<Input type="search" placeholder="Search..." onChange={handleSearch} />
</div>
<Separator />
<SearchResult query={query} className="flex-1"/>
<div className="p-4">

<h2>Query: {query}</h2>
<div className="overflow-auto flex-1">
<SearchResult query={query} resultList={resultList} />
<div ref={loadRef}>
{loading ? "laoding" : ""}
{loading && (
<div className="p-3 pl-6 grid gap-1 relative">
<Skeleton className="h-5 w-full" />
<div>
<Skeleton className="h-3 w-full" />
</div>
<div>
<Skeleton className="h-3 w-full m-[-2px]" />
</div>
<div>
<Skeleton className="h-3 w-32" />
</div>
</div>
)}
</div>
<div ref={observerTarget}>2</div>
</div>
<div className="p-4"></div>
</div>
);
};

0 comments on commit b925932

Please sign in to comment.