Yuki Takei 2 лет назад
Родитель
Сommit
144deb7c85

+ 19 - 13
apps/app/src/client/services/search-operation.ts

@@ -5,11 +5,11 @@ import { useRouter } from 'next/router';
 import useSWRImmutable from 'swr/immutable';
 
 
-type UseSearchOperation = {
-  search: (newKeyword: string, ignorePushingState?: boolean) => void,
+type UseKeywordManagerUtils = {
+  pushState: (newKeyword: string) => void,
 }
 
-export const useSearchOperation = (): SWRResponseWithUtils<UseSearchOperation, string> => {
+export const useKeywordManager = (): SWRResponseWithUtils<UseKeywordManagerUtils, string> => {
   // routerRef solve the problem of infinite redrawing that occurs with routers
   const router = useRouter();
   const routerRef = useRef(router);
@@ -23,17 +23,23 @@ export const useSearchOperation = (): SWRResponseWithUtils<UseSearchOperation, s
   });
 
   const { mutate } = swrResponse;
-  const search = useCallback((newKeyword: string, ignorePushingState?: boolean) => {
-    mutate(newKeyword);
-
-    if (ignorePushingState !== true) {
-      const newUrl = new URL('/_search', 'http://example.com');
-      newUrl.searchParams.append('q', newKeyword);
-      // routerRef.current.push(`${newUrl.pathname}${newUrl.search}`, '', { shallow: true });
-      routerRef.current.push(`${newUrl.pathname}${newUrl.search}`, '');
-    }
+  const pushState = useCallback((newKeyword: string) => {
+    mutate((prevKeyword) => {
+      if (prevKeyword !== newKeyword) {
+        const newUrl = new URL('/_search', 'http://example.com');
+        newUrl.searchParams.append('q', newKeyword);
+        routerRef.current.push(`${newUrl.pathname}${newUrl.search}`, '');
+      }
+
+      return newKeyword;
+    });
   }, [mutate]);
 
+  // detect search keyword from the query of URL
+  useEffect(() => {
+    mutate(initialKeyword);
+  }, [mutate, initialKeyword]);
+
   // browser back and forward
   useEffect(() => {
     routerRef.current.beforePopState(({ url }) => {
@@ -47,6 +53,6 @@ export const useSearchOperation = (): SWRResponseWithUtils<UseSearchOperation, s
   }, [mutate]);
 
   return withUtils(swrResponse, {
-    search,
+    pushState,
   });
 };

+ 5 - 5
apps/app/src/components/SearchPage.tsx

@@ -5,7 +5,7 @@ import React, {
 import { useTranslation } from 'next-i18next';
 
 import type { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all';
-import { useSearchOperation } from '~/client/services/search-operation';
+import { useKeywordManager } from '~/client/services/search-operation';
 import type { IFormattedSearchResult } from '~/interfaces/search';
 import { useIsSearchServiceReachable, useShowPageLimitationL } from '~/stores/context';
 import { type ISearchConditions, type ISearchConfigurations, useSWRxSearch } from '~/stores/search';
@@ -91,7 +91,7 @@ export const SearchPage = (): JSX.Element => {
   const { t } = useTranslation();
   const { data: showPageLimitationL } = useShowPageLimitationL();
 
-  const { data: keyword, search } = useSearchOperation();
+  const { data: keyword, pushState } = useKeywordManager();
 
   const [offset, setOffset] = useState<number>(0);
   const [limit, setLimit] = useState<number>(showPageLimitationL ?? INITIAL_PAGIONG_SIZE);
@@ -111,10 +111,10 @@ export const SearchPage = (): JSX.Element => {
     setOffset(0);
     setConfigurationsByControl(newConfigurations);
 
-    const ignorePushingState = keyword === newKeyword;
-    search(newKeyword, ignorePushingState);
+    pushState(newKeyword);
+
     mutate();
-  }, [keyword, mutate, search]);
+  }, [keyword, mutate, pushState]);
 
   const selectAllCheckboxChangedHandler = useCallback((isChecked: boolean) => {
     const instance = searchPageBaseRef.current;

+ 5 - 4
apps/app/src/components/TagList.tsx

@@ -4,7 +4,7 @@ import React, {
 
 import { useTranslation } from 'next-i18next';
 
-import { useSearchOperation } from '~/client/services/search-operation';
+import { useKeywordManager } from '~/client/services/search-operation';
 import { IDataTagCount } from '~/interfaces/tag';
 
 import PaginationWrapper from './PaginationWrapper';
@@ -29,22 +29,23 @@ const TagList: FC<TagListProps> = (props:(TagListProps & typeof defaultProps)) =
   const isTagExist: boolean = tagData.length > 0;
   const { t } = useTranslation('');
 
-  const { search } = useSearchOperation();
+  const { pushState } = useKeywordManager();
 
   const generateTagList = useCallback((tagData) => {
     return tagData.map((tag:IDataTagCount) => {
       return (
         <button
           key={tag._id}
+          type="button"
           className="list-group-item list-group-item-action d-flex"
-          onClick={() => search(`tag:${tag.name}`)}
+          onClick={() => pushState(`tag:${tag.name}`)}
         >
           <div className="text-truncate list-tag-name">{tag.name}</div>
           <div className="ml-4 my-auto py-1 px-2 list-tag-count badge badge-secondary text-white">{tag.count}</div>
         </button>
       );
     });
-  }, [search]);
+  }, [pushState]);
 
   if (!isTagExist) {
     return <h3>{ t('You have no tag, You can set tags on pages') }</h3>;