浏览代码

chore: useQueryList 增加特殊情况针对物料列表

xyh 2 年之前
父节点
当前提交
9ac42238d9

+ 63 - 0
packages/app/src/hooks/useQueryList/index.test.tsx

@@ -101,4 +101,67 @@ describe('useQueryList', function() {
       expect(getByTestId('list').children.length).toBe(2);
     });
   });
+
+  it('格式化result', async function() {
+    const pageContext = createPageContext();
+    const searchContext = createSearchContext();
+    const client = new QueryClient();
+
+    const App: FC = function() {
+      const [{isFetching, data, count}] = useQueryList({
+        queryFn: mockQuery,
+        params: {},
+        pageContext,
+        searchContext,
+        formatResult(data) {
+          return data.msg === '200'
+            ? data.data.list.map(val => val + 1)
+            : [];
+        },
+      });
+      const [,{onCurrentPageChange}] = usePage(pageContext);
+      function onNextPage() {
+        onCurrentPageChange(2);
+      }
+
+      return (
+        <>
+          <p data-testid='count'>{count}</p>
+          <p data-testid='is_fetching'>{isFetching.toString()}</p>
+          <button data-testid='next_page' onClick={onNextPage} />
+          <ul data-testid='list'>
+            {data.map(function(val) {
+              return <li key={val}>{val}</li>;
+            })}
+          </ul>
+        </>
+      );
+    };
+
+    const {getByTestId} = render(
+      <QueryClientProvider client={client}>
+        <PageProvider context={pageContext}>
+          <App />
+        </PageProvider>
+      </QueryClientProvider>,
+    );
+
+    await waitFor(function() {
+      expect(getByTestId('count').innerHTML).toBe('0');
+      expect(getByTestId('is_fetching').innerHTML).toBe('true');
+      expect(getByTestId('list').children.length).toBe(0);
+    });
+
+    await waitFor(function() {
+      expect(getByTestId('count').innerHTML).toBe('4');
+      expect(getByTestId('is_fetching').innerHTML).toBe('false');
+      const list = getByTestId('list');
+      expect(list.children.length).toBe(4);
+
+      expect(list.children[0].innerHTML).toBe('2');
+      expect(list.children[1].innerHTML).toBe('3');
+      expect(list.children[2].innerHTML).toBe('4');
+      expect(list.children[3].innerHTML).toBe('5');
+    });
+  });
 });

+ 23 - 12
packages/app/src/hooks/useQueryList/index.ts

@@ -2,12 +2,13 @@ import {createPageContext, createSearchContext, usePage, useTableSearchState} fr
 import {BaseListResult, GetBaseListType, ListParams, OriginalListParams} from '@models';
 import {useQuery} from '@tanstack/react-query';
 import {shallowEqual} from '@utils';
+import {useLatest} from 'ahooks';
 import {useEffect, useRef, useState} from 'react';
 
-type UseQueryListResult<D extends BaseListResult> = [
+type UseQueryListResult<D extends BaseListResult, T extends unknown[] = GetBaseListType<D>[]> = [
   {
     count: number,
-    data: GetBaseListType<D>[],
+    data: T,
     isFetching: boolean,
   },
   {refetch: () => void},
@@ -16,26 +17,30 @@ type UseQueryListResult<D extends BaseListResult> = [
 type UseQueryListOptions<
   P extends ListParams,
   R extends BaseListResult,
+  T extends Array<unknown> = GetBaseListType<R>[],
 > = {
   queryFn: (params: P) => R,
   params: OriginalListParams<P>,
   pageContext: ReturnType<typeof createPageContext>,
   searchContext: ReturnType<typeof createSearchContext>,
+  formatResult?: (data: Awaited<R>) => T,
 };
 
 export function useQueryTableList<
   P extends ListParams,
   R extends BaseListResult,
+  T extends Array<unknown> = GetBaseListType<R>[],
 >(
-  {queryFn, params, pageContext, searchContext}: UseQueryListOptions<P, R>,
-): UseQueryListResult<R> {
+  {queryFn, params, pageContext, searchContext, formatResult}: UseQueryListOptions<P, R, T>,
+): UseQueryListResult<R, T> {
   const [count, setCount] = useState(0);
   const [{page, pageSize}, {onCurrentPageChange}] = usePage(pageContext);
-  const prevData = useRef<R[]>([]);
+  const prevData = useRef<T>([] as unknown as T);
   const prevParams = useRef(params);
+  const formatResultFn = useLatest(formatResult);
 
-  const {data = [], isFetching, refetch} = useQuery<GetBaseListType<R>[]>(
-    [queryFn.name, page, pageSize, ...Object.values(params)],
+  const {data = [] as unknown as T, isFetching, refetch} = useQuery<T>(
+    [queryFn.name, page, pageSize, formatResultFn, ...Object.values(params)],
     async function() {
       /**
        * 当参数发生改变说明请求内容发生变化
@@ -44,6 +49,8 @@ export function useQueryTableList<
       if (page !== 1 && !shallowEqual(prevParams.current, params)) {
         prevParams.current = params;
         onCurrentPageChange(1);
+        // 这里可以返回一个空数组
+        // 记录上一次数据是为了展示 防止闪烁
         return prevData.current;
       }
 
@@ -63,20 +70,24 @@ export function useQueryTableList<
         const {total, list} = data.data;
 
         /**
-         * 当页面只有一个数据的时候 删除了页码改为前一个 但是数据请求还是当前页码
+         * 场景:当页面只有一个数据的时候 删除了页码改为前一个 但是数据请求还是当前页码
          * 需要判断当前是否无数据并且页码大于1 满足时跳转到前一个页面
          */
         page > 1 && list.length === 0 && onCurrentPageChange(page - 1);
 
         setCount(total);
-
-        return (prevData.current = list);
       }
 
-      return [];
+      let res: T;
+
+      formatResultFn.current
+        ? res = formatResultFn.current(data)
+        : res = data.msg === '200' ? data.data.list as unknown as T : [] as unknown as T;
+
+      return (prevData.current = res);
     },
     {
-      placeholderData: [],
+      placeholderData: [] as unknown as T,
       keepPreviousData: true,
     },
   );

+ 1 - 1
packages/app/src/index.tsx

@@ -46,7 +46,7 @@ root.render(
           </BrowserRouter>
         </Suspense>
       </ConfigProvider>
-      {/* <ReactQueryDevtools initialIsOpen={false} position='bottom-right' /> */}
+      <ReactQueryDevtools initialIsOpen={false} position='bottom-right' />
     </QueryClientProvider>
   </StrictMode>,
 );

+ 11 - 58
packages/app/src/pages/goods/table/hooks.tsx

@@ -1,13 +1,11 @@
-import {useContextSection, usePage, useTableSearchState} from '@hooks';
+import {useContextSection, useQueryTableList} from '@hooks';
 import {context, pageContext, searchContext} from '../context';
 import {getDictionaryList} from '@apis';
 import {DictionaryData, DictionaryParamsType} from '@models';
 import {Button} from 'antd';
 import {ColumnsType} from 'antd/es/table';
-import {useEffect, useRef, useState} from 'react';
+import {useState} from 'react';
 import {useBoolean} from 'ahooks';
-import {shallowEqual} from '@utils';
-import {useQuery} from '@tanstack/react-query';
 
 type MaterialType = DictionaryData & {count: number};
 
@@ -19,46 +17,14 @@ export function useList() {
     },
   );
 
-  const [count, setCount] = useState(0);
-  const [{page, pageSize}, {onCurrentPageChange}] = usePage(pageContext);
-  const prevData = useRef<MaterialType[]>([]);
-  const prevParams = useRef(params);
-
-  const {data = [], isFetching, refetch} = useQuery<MaterialType[]>(
-    [getDictionaryList.name, page, pageSize, ...Object.values(params)],
-    async function() {
-      /**
-       * 当参数发生改变说明请求内容发生变化
-       * 如果当前页码不为1需要跳转到第1页查询
-       */
-      if (page !== 1 && !shallowEqual(prevParams.current, params)) {
-        prevParams.current = params;
-        onCurrentPageChange(1);
-        return prevData.current;
-      }
-
-      /**
-       * 有可能参数发生变化但是页码为1 第一步不会拦截
-       * 这里确保参数是最新的参数
-       */
-      prevParams.current = params;
-
-      const data = await getDictionaryList({
-        ...params,
-        page: page.toString(),
-        limit: pageSize.toString(),
-      });
-
+  return useQueryTableList({
+    params,
+    queryFn: getDictionaryList,
+    pageContext,
+    searchContext,
+    formatResult(data) {
       if (data.msg === '200') {
-        const {data: {total, list}, amount} = data;
-
-        /**
-         * 当页面只有一个数据的时候 删除了页码改为前一个 但是数据请求还是当前页码
-         * 需要判断当前是否无数据并且页码大于1 满足时跳转到前一个页面
-         */
-        page > 1 && list.length === 0 && onCurrentPageChange(page - 1);
-
-        setCount(total);
+        const {data: {list}, amount} = data;
 
         const arr = list.map<MaterialType>(function(val) {
           return {
@@ -67,25 +33,12 @@ export function useList() {
           };
         });
 
-        return (prevData.current = arr);
+        return arr;
       }
 
       return [];
     },
-    {
-      placeholderData: [],
-      keepPreviousData: true,
-    },
-  );
-
-  const [, searchChange] = useTableSearchState(searchContext);
-
-  // 保持更新搜索表格的查询状态
-  useEffect(function() {
-    searchChange(isFetching);
-  }, [isFetching, searchChange]);
-
-  return [{data, count}, {refetch}] as const;
+  });
 }
 
 export function useEdit() {