Procházet zdrojové kódy

migrate SWR to v2

update fetcher arguments
Yuki Takei před 3 roky
rodič
revize
504e98d0ae

+ 1 - 1
packages/app/src/stores/editor.tsx

@@ -39,7 +39,7 @@ export const useEditorSettings = (): SWRResponseWithUtils<EditorSettingsOperatio
   const { data: currentUser } = useCurrentUser();
   const { data: isGuestUser } = useIsGuestUser();
 
-  const swrResult = useSWRImmutable<IEditorSettings>(
+  const swrResult = useSWRImmutable(
     isGuestUser ? null : ['/personal-setting/editor-settings', currentUser?.username],
     ([endpoint]) => apiv3Get(endpoint).then(result => result.data),
     {

+ 2 - 2
packages/app/src/stores/page-listing.tsx

@@ -18,7 +18,7 @@ import { ITermNumberManagerUtil, useTermNumberManager } from './use-static-swr';
 
 export const useSWRxPagesByPath = (path?: Nullable<string>): SWRResponse<IPageHasId[], Error> => {
   const findAll = true;
-  return useSWR<IPageHasId[], Error>(
+  return useSWR(
     path != null ? ['/page', path, findAll] : null,
     ([endpoint, path, findAll]) => apiv3Get(endpoint, { path, findAll }).then(result => result.data.pages),
   );
@@ -105,7 +105,7 @@ export const useSWRxPageInfoForList = (
 
   const shouldFetch = (pageIds != null && pageIds.length > 0) || path != null;
 
-  const swrResult = useSWRImmutable<Record<string, IPageInfoForListing>>(
+  const swrResult = useSWRImmutable(
     shouldFetch ? ['/page-listing/info', pageIds, path, attachBookmarkCount, attachShortBody] : null,
     ([endpoint, pageIds, path, attachBookmarkCount, attachShortBody]) => {
       return apiv3Get(endpoint, {

+ 26 - 23
packages/app/src/stores/page.tsx

@@ -29,22 +29,25 @@ export const useSWRxPage = (
     initialData?: IPagePopulatedToShowRevision|null,
     config?: SWRConfiguration,
 ): SWRResponse<IPagePopulatedToShowRevision|null, Error> => {
-  const swrResponse = useSWRImmutable<IPagePopulatedToShowRevision|null, Error>(
+
+  const swrResponse = useSWRImmutable(
     pageId != null ? ['/page', pageId, shareLinkId, revisionId] : null,
     // TODO: upgrade SWR to v2 and use useSWRMutation
     //        in order to avoid complicated fetcher settings
     Object.assign({
-      fetcher: (endpoint, pageId, shareLinkId, revisionId) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { pageId, shareLinkId, revisionId })
-        .then(result => result.data.page)
-        .catch((errs) => {
-          if (!Array.isArray(errs)) { throw Error('error is not array') }
-          const statusCode = errs[0].status;
-          if (statusCode === 403 || statusCode === 404) {
-            // for NotFoundPage
-            return null;
-          }
-          throw Error('failed to get page');
-        }),
+      fetcher: ([endpoint, pageId, shareLinkId, revisionId]: [string, string, string|undefined, string|undefined]) => {
+        return apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { pageId, shareLinkId, revisionId })
+          .then(result => result.data.page)
+          .catch((errs) => {
+            if (!Array.isArray(errs)) { throw Error('error is not array') }
+            const statusCode = errs[0].status;
+            if (statusCode === 403 || statusCode === 404) {
+              // for NotFoundPage
+              return null;
+            }
+            throw Error('failed to get page');
+          });
+      },
     }, config ?? {}),
   );
 
@@ -59,9 +62,9 @@ export const useSWRxPage = (
 };
 
 export const useSWRxPageByPath = (path?: string): SWRResponse<IPagePopulatedToShowRevision, Error> => {
-  return useSWR<IPagePopulatedToShowRevision, Error>(
+  return useSWR(
     path != null ? ['/page', path] : null,
-    (endpoint, path) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { path }).then(result => result.data.page),
+    ([endpoint, path]) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { path }).then(result => result.data.page),
   );
 };
 
@@ -97,9 +100,9 @@ export const useSWRxTagsInfo = (pageId: Nullable<string>): SWRResponse<IPageTags
 
   const endpoint = `/pages.getPageTag?pageId=${pageId}`;
 
-  return useSWRImmutable<IPageTagsInfo | undefined, Error>(
+  return useSWRImmutable(
     shareLinkId == null && pageId != null ? [endpoint, pageId] : null,
-    (endpoint, pageId) => apiGet<IPageTagsInfo>(endpoint, { pageId }).then(result => result),
+    ([endpoint, pageId]) => apiGet<IPageTagsInfo>(endpoint, { pageId }).then(result => result),
   );
 };
 
@@ -118,9 +121,9 @@ export const useSWRxPageInfo = (
   // assign null if shareLinkId is undefined in order to identify SWR key only by pageId
   const fixedShareLinkId = shareLinkId ?? null;
 
-  const swrResult = useSWRImmutable<IPageInfo | IPageInfoForOperation, Error>(
+  const swrResult = useSWRImmutable(
     pageId != null && termNumber != null ? ['/page/info', pageId, fixedShareLinkId, termNumber] : null,
-    (endpoint, pageId, shareLinkId) => apiv3Get(endpoint, { pageId, shareLinkId }).then(response => response.data),
+    ([endpoint, pageId, shareLinkId]) => apiv3Get(endpoint, { pageId, shareLinkId }).then(response => response.data),
     { fallbackData: initialData },
   );
 
@@ -133,9 +136,9 @@ export const useSWRxPageRevisions = (
     pageId: string | null | undefined,
 ): SWRResponse<IRevisionsForPagination, Error> => {
 
-  return useSWRImmutable<IRevisionsForPagination, Error>(
+  return useSWRImmutable(
     ['/revisions/list', pageId, page, limit],
-    (endpoint, pageId, page, limit) => {
+    ([endpoint, pageId, page, limit]) => {
       return apiv3Get(endpoint, { pageId, page, limit }).then((response) => {
         const revisions = {
           revisions: response.data.docs,
@@ -166,7 +169,7 @@ export const useSWRxApplicableGrant = (
 
   return useSWRImmutable(
     pageId != null ? ['/page/applicable-grant', pageId] : null,
-    (endpoint, pageId) => apiv3Get(endpoint, { pageId }).then(response => response.data),
+    ([endpoint, pageId]) => apiv3Get(endpoint, { pageId }).then(response => response.data),
   );
 };
 
@@ -181,7 +184,7 @@ export const useCurrentPagePath = (): SWRResponse<string | undefined, Error> =>
 
   return useSWRImmutable(
     ['currentPagePath', currentPage?.path, currentPathname],
-    (key: Key, pagePath: string|undefined, pathname: string|undefined) => {
+    ([, , pathname]) => {
       if (currentPage?.path != null) {
         return currentPage.path;
       }
@@ -200,7 +203,7 @@ export const useIsTrashPage = (): SWRResponse<boolean, Error> => {
 
   return useSWRImmutable(
     pagePath == null ? null : ['isTrashPage', pagePath],
-    (key: Key, pagePath: string) => pagePathUtils.isTrashPage(pagePath),
+    ([, pagePath]) => pagePathUtils.isTrashPage(pagePath),
     // TODO: set fallbackData
     // { fallbackData:  }
   );

+ 31 - 43
packages/app/src/stores/renderer.tsx

@@ -23,13 +23,11 @@ export const useViewOptions = (storeTocNodeHandler: (toc: HtmlElementNode) => vo
 
   const isAllDataValid = currentPagePath != null && rendererConfig != null;
 
-  const key = isAllDataValid
-    ? ['viewOptions', currentPagePath, rendererConfig]
-    : null;
-
-  return useSWR<RendererOptions, Error>(
-    key,
-    (rendererId, currentPagePath, rendererConfig) => {
+  return useSWR(
+    isAllDataValid
+      ? ['viewOptions', currentPagePath, rendererConfig]
+      : null,
+    ([, currentPagePath, rendererConfig]) => {
       // determine options generator
       const optionsGenerator = getGrowiFacade().markdownRenderer?.optionsGenerators?.customGenerateViewOptions ?? generateViewOptions;
       return optionsGenerator(currentPagePath, rendererConfig, storeTocNodeHandler);
@@ -47,13 +45,11 @@ export const useTocOptions = (): SWRResponse<RendererOptions, Error> => {
 
   const isAllDataValid = currentPagePath != null && rendererConfig != null && tocNode != null;
 
-  const key = isAllDataValid
-    ? ['tocOptions', currentPagePath, tocNode, rendererConfig]
-    : null;
-
-  return useSWRImmutable<RendererOptions, Error>(
-    key,
-    (rendererId, path, tocNode, rendererConfig) => generateTocOptions(rendererConfig, tocNode),
+  return useSWRImmutable(
+    isAllDataValid
+      ? ['tocOptions', currentPagePath, tocNode, rendererConfig]
+      : null,
+    ([, , tocNode, rendererConfig]) => generateTocOptions(rendererConfig, tocNode),
     {
       fallbackData: isAllDataValid ? generateTocOptions(rendererConfig, tocNode) : undefined,
     },
@@ -66,16 +62,14 @@ export const usePreviewOptions = (): SWRResponse<RendererOptions, Error> => {
 
   const isAllDataValid = currentPagePath != null && rendererConfig != null;
 
-  const key = isAllDataValid
-    ? ['previewOptions', rendererConfig, currentPagePath]
-    : null;
-
-  return useSWR<RendererOptions, Error>(
-    key,
-    (rendererId, rendererConfig, pagePath, highlightKeywords) => {
+  return useSWR(
+    isAllDataValid
+      ? ['previewOptions', rendererConfig, currentPagePath]
+      : null,
+    ([, rendererConfig, pagePath]) => {
       // determine options generator
       const optionsGenerator = getGrowiFacade().markdownRenderer?.optionsGenerators?.customGeneratePreviewOptions ?? generatePreviewOptions;
-      return optionsGenerator(rendererConfig, pagePath, highlightKeywords);
+      return optionsGenerator(rendererConfig, pagePath);
     },
     {
       fallbackData: isAllDataValid ? generatePreviewOptions(rendererConfig, currentPagePath) : undefined,
@@ -89,13 +83,11 @@ export const useCommentForCurrentPageOptions = (): SWRResponse<RendererOptions,
 
   const isAllDataValid = currentPagePath != null && rendererConfig != null;
 
-  const key = isAllDataValid
-    ? ['commentPreviewOptions', rendererConfig, currentPagePath]
-    : null;
-
-  return useSWRImmutable<RendererOptions, Error>(
-    key,
-    (rendererId, rendererConfig, currentPagePath) => generateSimpleViewOptions(
+  return useSWRImmutable(
+    isAllDataValid
+      ? ['commentPreviewOptions', rendererConfig, currentPagePath]
+      : null,
+    ([, rendererConfig, currentPagePath]) => generateSimpleViewOptions(
       rendererConfig,
       currentPagePath,
       undefined,
@@ -118,13 +110,11 @@ export const useSelectedPagePreviewOptions = (pagePath: string, highlightKeyword
 
   const isAllDataValid = rendererConfig != null;
 
-  const key = isAllDataValid
-    ? ['selectedPagePreviewOptions', rendererConfig, pagePath, highlightKeywords]
-    : null;
-
-  return useSWRImmutable<RendererOptions, Error>(
-    key,
-    (rendererId, rendererConfig, pagePath, highlightKeywords) => generateSimpleViewOptions(rendererConfig, pagePath, highlightKeywords),
+  return useSWRImmutable(
+    isAllDataValid
+      ? ['selectedPagePreviewOptions', rendererConfig, pagePath, highlightKeywords]
+      : null,
+    ([, rendererConfig, pagePath, highlightKeywords]) => generateSimpleViewOptions(rendererConfig, pagePath, highlightKeywords),
     {
       fallbackData: isAllDataValid ? generateSimpleViewOptions(rendererConfig, pagePath, highlightKeywords) : undefined,
     },
@@ -139,13 +129,11 @@ export const useCustomSidebarOptions = (): SWRResponse<RendererOptions, Error> =
 
   const isAllDataValid = rendererConfig != null;
 
-  const key = isAllDataValid
-    ? ['customSidebarOptions', rendererConfig]
-    : null;
-
-  return useSWRImmutable<RendererOptions, Error>(
-    key,
-    (rendererId, rendererConfig, pagePath, highlightKeywords) => generateSimpleViewOptions(rendererConfig, pagePath, highlightKeywords),
+  return useSWRImmutable(
+    isAllDataValid
+      ? ['customSidebarOptions', rendererConfig]
+      : null,
+    ([, rendererConfig]) => generateSimpleViewOptions(rendererConfig, '/'),
     {
       fallbackData: isAllDataValid ? generateSimpleViewOptions(rendererConfig, '/') : undefined,
     },

+ 1 - 2
packages/app/src/stores/search.tsx

@@ -2,7 +2,6 @@ import { SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
 import { apiGet } from '~/client/util/apiv1-client';
-
 import { IFormattedSearchResult, SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
 
 import { ITermNumberManagerUtil, useTermNumberManager } from './use-static-swr';
@@ -73,7 +72,7 @@ export const useSWRxSearch = (
 
   const swrResult = useSWRImmutable(
     isKeywordValid ? ['/search', keyword, fixedConfigurations, termNumber] : null,
-    (endpoint, keyword, fixedConfigurations) => {
+    ([endpoint, , fixedConfigurations]) => {
       const {
         limit, offset, sort, order,
       } = fixedConfigurations;

+ 4 - 1
packages/app/src/stores/share-link.tsx

@@ -10,5 +10,8 @@ const fetchShareLinks = async(endpoint, pageId) => {
 };
 
 export const useSWRxSharelink = (currentPageId: Nullable<string>): SWRResponse<IResShareLinkList['shareLinksResult'], Error> => {
-  return useSWR(currentPageId == null ? null : ['/share-links/', currentPageId], (endpoint => fetchShareLinks(endpoint, currentPageId)));
+  return useSWR(
+    currentPageId == null ? null : ['/share-links/', currentPageId],
+    ([endpoint]) => fetchShareLinks(endpoint, currentPageId),
+  );
 };

+ 2 - 2
packages/app/src/stores/tag.tsx

@@ -7,13 +7,13 @@ import { IResTagsListApiv1, IResTagsSearchApiv1 } from '~/interfaces/tag';
 export const useSWRxTagsList = (limit?: number, offset?: number): SWRResponse<IResTagsListApiv1, Error> => {
   return useSWRImmutable(
     ['/tags.list', limit, offset],
-    (endpoint, limit, offset) => apiGet(endpoint, { limit, offset }).then((result: IResTagsListApiv1) => result),
+    ([endpoint, limit, offset]) => apiGet(endpoint, { limit, offset }).then((result: IResTagsListApiv1) => result),
   );
 };
 
 export const useSWRxTagsSearch = (query: string): SWRResponse<IResTagsSearchApiv1, Error> => {
   return useSWRImmutable(
     ['/tags.search', query],
-    (endpoint, query) => apiGet(endpoint, { q: query }).then((result: IResTagsSearchApiv1) => result),
+    ([endpoint, query]) => apiGet(endpoint, { q: query }).then((result: IResTagsSearchApiv1) => result),
   );
 };

+ 1 - 1
packages/app/src/stores/template.tsx

@@ -48,7 +48,7 @@ yyyy/mm/dd (予定、時間は追って連絡)`,
 ];
 
 export const useTemplates = (): SWRResponse<ITemplate[], Error> => {
-  return useSWR<ITemplate[], Error>(
+  return useSWR(
     'templates',
     () => [
       ...presetTemplates,

+ 23 - 17
packages/app/src/stores/ui.tsx

@@ -8,7 +8,7 @@ import { Breakpoint, addBreakpointListener, cleanupBreakpointListener } from '@g
 import { HtmlElementNode } from 'rehype-toc';
 import type SimpleBar from 'simplebar-react';
 import {
-  useSWRConfig, SWRResponse, Key, Fetcher,
+  useSWRConfig, SWRResponse, Key,
 } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
@@ -155,7 +155,7 @@ export const useEditorMode = (): SWRResponseWithUtils<EditorModeUtils, EditorMod
   const isEditable = !isLoading && _isEditable;
   const initialData = isEditable ? editorModeByHash : EditorMode.View;
 
-  const swrResponse = useSWRImmutable<EditorMode>(
+  const swrResponse = useSWRImmutable(
     isLoading ? null : ['editorMode', isEditable],
     null,
     { fallbackData: initialData },
@@ -260,7 +260,7 @@ export const usePreferDrawerModeByUser = (initialData?: boolean): SWRResponseWit
     },
   };
 
-  return withUtils(swrResponse, utils);
+  return withUtils<PreferDrawerModeByUserUtils>(swrResponse, utils);
 
 };
 
@@ -286,29 +286,36 @@ export const useDrawerMode = (): SWRResponse<boolean, Error> => {
   const { data: editorMode } = useEditorMode();
   const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd();
 
-  const condition = editorMode != null || preferDrawerModeByUser != null || preferDrawerModeOnEditByUser != null || isDeviceSmallerThanMd != null;
+  const condition = editorMode != null && preferDrawerModeByUser != null && preferDrawerModeOnEditByUser != null && isDeviceSmallerThanMd != null;
 
-  const calcDrawerMode: Fetcher<boolean> = (
-      key: Key, editorMode: EditorMode, preferDrawerModeByUser: boolean, preferDrawerModeOnEditByUser: boolean, isDeviceSmallerThanMd: boolean,
+  const calcDrawerMode = (
+      endpoint: string,
+      editorMode: EditorMode,
+      preferDrawerModeByUser: boolean,
+      preferDrawerModeOnEditByUser: boolean,
+      isDeviceSmallerThanMd: boolean,
   ): boolean => {
-
     // get preference on view or edit
     const preferDrawerMode = editorMode !== EditorMode.View ? preferDrawerModeOnEditByUser : preferDrawerModeByUser;
 
-    return isDeviceSmallerThanMd || preferDrawerMode;
+    return isDeviceSmallerThanMd ?? preferDrawerMode ?? false;
   };
 
   const isViewModeWithPreferDrawerMode = editorMode === EditorMode.View && preferDrawerModeByUser;
   const isEditModeWithPreferDrawerMode = editorMode === EditorMode.Editor && preferDrawerModeOnEditByUser;
-  const useFallbackData = isViewModeWithPreferDrawerMode || isEditModeWithPreferDrawerMode;
-  const fallbackOption = useFallbackData
-    ? { fallbackData: true }
-    : { fallback: calcDrawerMode };
+  const isDrawerModeFixed = isViewModeWithPreferDrawerMode || isEditModeWithPreferDrawerMode;
 
   return useSWRImmutable(
     condition ? ['isDrawerMode', editorMode, preferDrawerModeByUser, preferDrawerModeOnEditByUser, isDeviceSmallerThanMd] : null,
-    calcDrawerMode,
-    fallbackOption,
+    // calcDrawerMode,
+    key => calcDrawerMode(...key),
+    condition
+      ? {
+        fallbackData: isDrawerModeFixed
+          ? true
+          : calcDrawerMode('isDrawerMode', editorMode, preferDrawerModeByUser, preferDrawerModeOnEditByUser, isDeviceSmallerThanMd),
+      }
+      : undefined,
   );
 };
 
@@ -321,7 +328,7 @@ type SidebarConfigOption = {
 }
 
 export const useSWRxSidebarConfig = (): SWRResponse<ISidebarConfig, Error> & SidebarConfigOption => {
-  const swrResponse = useSWRImmutable<ISidebarConfig>(
+  const swrResponse = useSWRImmutable(
     '/customize-setting/sidebar',
     endpoint => apiv3Get(endpoint).then(result => result.data),
   );
@@ -439,8 +446,7 @@ export const useIsAbleToShowPageManagement = (): SWRResponse<boolean, Error> =>
 
   return useSWRImmutable(
     includesUndefined ? null : [key, pageId, isPageExist, isEmptyPage, isTrashPage, isSharedUser],
-    // eslint-disable-next-line max-len
-    (key: string, pageId: string, isPageExist: boolean, isTrashPage: boolean, isSharedUser: boolean) => (isPageExist && !isTrashPage && !isSharedUser) || isEmptyPage,
+    ([, ,, isPageExist, isTrashPage, isSharedUser]) => (isPageExist && !isTrashPage && !isSharedUser) || isEmptyPage,
   );
 };
 

+ 1 - 1
packages/app/src/stores/use-context-swr.tsx

@@ -28,7 +28,7 @@ export function useContextSWR<Data, Error>(
 
   // write data to cache directly
   if (data !== undefined) {
-    cache.set(key, data);
+    cache.set(key, { ...cache.get(key), data });
   }
 
   const result = Object.assign(swrResponse, { mutate: () => { throw Error('mutate can not be used in context') } });

+ 11 - 11
packages/app/src/stores/user-group.tsx

@@ -25,13 +25,13 @@ export const useSWRxMyUserGroupRelations = (shouldFetch: boolean): SWRResponse<I
 
 export const useSWRxUserGroup = (groupId: string | undefined): SWRResponse<IUserGroupHasId, Error> => {
   return useSWRImmutable(
-    groupId != null ? [`/user-groups/${groupId}`] : null,
+    groupId != null ? `/user-groups/${groupId}` : null,
     endpoint => apiv3Get<UserGroupResult>(endpoint).then(result => result.data.userGroup),
   );
 };
 
 export const useSWRxUserGroupList = (initialData?: IUserGroupHasId[]): SWRResponse<IUserGroupHasId[], Error> => {
-  return useSWRImmutable<IUserGroupHasId[], Error>(
+  return useSWRImmutable(
     '/user-groups',
     endpoint => apiv3Get<UserGroupListResult>(endpoint, { pagination: false }).then(result => result.data.userGroups),
     {
@@ -44,9 +44,9 @@ export const useSWRxChildUserGroupList = (
     parentIds?: string[], includeGrandChildren?: boolean,
 ): SWRResponse<ChildUserGroupListResult, Error> => {
   const shouldFetch = parentIds != null && parentIds.length > 0;
-  return useSWRImmutable<ChildUserGroupListResult, Error>(
+  return useSWRImmutable(
     shouldFetch ? ['/user-groups/children', parentIds, includeGrandChildren] : null,
-    (endpoint, parentIds, includeGrandChildren) => apiv3Get<ChildUserGroupListResult>(
+    ([endpoint, parentIds, includeGrandChildren]) => apiv3Get<ChildUserGroupListResult>(
       endpoint, { parentIds, includeGrandChildren },
     ).then((result => result.data)),
   );
@@ -54,7 +54,7 @@ export const useSWRxChildUserGroupList = (
 
 export const useSWRxUserGroupRelations = (groupId: string): SWRResponse<IUserGroupRelationHasIdPopulatedUser[], Error> => {
   return useSWRImmutable(
-    groupId != null ? [`/user-groups/${groupId}/user-group-relations`] : null,
+    groupId != null ? `/user-groups/${groupId}/user-group-relations` : null,
     endpoint => apiv3Get<UserGroupRelationsResult>(endpoint).then(result => result.data.userGroupRelations),
   );
 };
@@ -62,9 +62,9 @@ export const useSWRxUserGroupRelations = (groupId: string): SWRResponse<IUserGro
 export const useSWRxUserGroupRelationList = (
     groupIds: string[] | undefined, childGroupIds?: string[], initialData?: IUserGroupRelationHasId[],
 ): SWRResponse<IUserGroupRelationHasId[], Error> => {
-  return useSWRImmutable<IUserGroupRelationHasId[], Error>(
+  return useSWRImmutable(
     groupIds != null ? ['/user-group-relations', groupIds, childGroupIds] : null,
-    (endpoint, groupIds, childGroupIds) => apiv3Get<UserGroupRelationListResult>(
+    ([endpoint, groupIds, childGroupIds]) => apiv3Get<UserGroupRelationListResult>(
       endpoint, { groupIds, childGroupIds },
     ).then(result => result.data.userGroupRelations),
     {
@@ -76,27 +76,27 @@ export const useSWRxUserGroupRelationList = (
 export const useSWRxUserGroupPages = (groupId: string | undefined, limit: number, offset: number): SWRResponse<IPageHasId[], Error> => {
   return useSWRImmutable(
     groupId != null ? [`/user-groups/${groupId}/pages`, limit, offset] : null,
-    endpoint => apiv3Get<UserGroupPagesResult>(endpoint, { limit, offset }).then(result => result.data.pages),
+    ([endpoint, limit, offset]) => apiv3Get<UserGroupPagesResult>(endpoint, { limit, offset }).then(result => result.data.pages),
   );
 };
 
 export const useSWRxSelectableParentUserGroups = (groupId: string | undefined): SWRResponse<IUserGroupHasId[], Error> => {
   return useSWRImmutable(
     groupId != null ? ['/user-groups/selectable-parent-groups', groupId] : null,
-    endpoint => apiv3Get<SelectableParentUserGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableParentGroups),
+    ([endpoint, groupId]) => apiv3Get<SelectableParentUserGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableParentGroups),
   );
 };
 
 export const useSWRxSelectableChildUserGroups = (groupId: string | undefined): SWRResponse<IUserGroupHasId[], Error> => {
   return useSWRImmutable(
     groupId != null ? ['/user-groups/selectable-child-groups', groupId] : null,
-    endpoint => apiv3Get<SelectableUserChildGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableChildGroups),
+    ([endpoint, groupId]) => apiv3Get<SelectableUserChildGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableChildGroups),
   );
 };
 
 export const useSWRxAncestorUserGroups = (groupId: string | undefined): SWRResponse<IUserGroupHasId[], Error> => {
   return useSWRImmutable(
     groupId != null ? ['/user-groups/ancestors', groupId] : null,
-    endpoint => apiv3Get<AncestorUserGroupsResult>(endpoint, { groupId }).then(result => result.data.ancestorUserGroups),
+    ([endpoint, groupId]) => apiv3Get<AncestorUserGroupsResult>(endpoint, { groupId }).then(result => result.data.ancestorUserGroups),
   );
 };

+ 2 - 2
packages/app/src/stores/user.tsx

@@ -9,7 +9,7 @@ export const useSWRxUsersList = (userIds: string[]): SWRResponse<IUserHasId[], E
   const distinctUserIds = userIds.length > 0 ? Array.from(new Set(userIds)).sort() : [];
   return useSWR(
     distinctUserIds.length > 0 ? ['/users/list', distinctUserIds] : null,
-    (endpoint, userIds) => apiv3Get(endpoint, { userIds: userIds.join(',') }).then((response) => {
+    ([endpoint, userIds]) => apiv3Get(endpoint, { userIds: userIds.join(',') }).then((response) => {
       return response.data.users;
     }),
     {
@@ -43,7 +43,7 @@ type usernameResult = {
 export const useSWRxUsernames = (q: string, offset?: number, limit?: number, options?: usernameRequestOptions): SWRResponse<usernameResult, Error> => {
   return useSWRImmutable(
     (q != null && q.trim() !== '') ? ['/users/usernames', q, offset, limit, options] : null,
-    (endpoint, q, offset, limit, options) => apiv3Get(endpoint, {
+    ([endpoint, q, offset, limit, options]) => apiv3Get(endpoint, {
       q, offset, limit, options,
     }).then(result => result.data),
   );

+ 3 - 1
packages/app/src/stores/xss.ts

@@ -1,8 +1,10 @@
 
-import { useStaticSWR } from './use-static-swr';
 import { SWRResponse } from 'swr';
+
 import Xss from '~/services/xss';
 
+import { useStaticSWR } from './use-static-swr';
+
 export const useXss = (initialData?: Xss): SWRResponse<Xss, Error> => {
   return useStaticSWR<Xss, Error>('xss', initialData);
 };