From 6c8395363339b7261e86d9cfed5c83f46d0eb6be Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Thu, 7 Dec 2023 19:26:07 +0100 Subject: [PATCH] Fix Infinite loop on invite route (#2866) --- .../effect-components/PageChangeEffect.tsx | 30 ++++--- front/src/hooks/useIsMatchingLocation.ts | 16 ++-- .../hooks/useOpenCreateActivityDrawer.ts | 87 ++++++++++--------- .../command-menu/hooks/useCommandMenu.ts | 10 ++- .../snack-bar-manager/hooks/useSnackBar.tsx | 22 ++--- 5 files changed, 93 insertions(+), 72 deletions(-) diff --git a/front/src/effect-components/PageChangeEffect.tsx b/front/src/effect-components/PageChangeEffect.tsx index afa5fbba7..f21b541d8 100644 --- a/front/src/effect-components/PageChangeEffect.tsx +++ b/front/src/effect-components/PageChangeEffect.tsx @@ -47,7 +47,9 @@ export const PageChangeEffect = () => { } else { return; } + }, [location, previousLocation]); + useEffect(() => { const isMachinOngoingUserCreationRoute = isMatchingLocation(AppPath.SignUp) || isMatchingLocation(AppPath.SignIn) || @@ -108,7 +110,16 @@ export const PageChangeEffect = () => { }, }); } + }, [ + enqueueSnackBar, + isMatchingLocation, + location.pathname, + navigate, + onboardingStatus, + workspaceFromInviteHashQuery, + ]); + useEffect(() => { switch (true) { case isMatchingLocation(AppPath.RecordTablePage): { setHotkeyScope(TableHotkeyScope.Table, { @@ -177,7 +188,9 @@ export const PageChangeEffect = () => { break; } } + }, [isMatchingLocation, setHotkeyScope]); + useEffect(() => { setToIntitialCommandMenu(); addToCommandMenu([ @@ -190,7 +203,9 @@ export const PageChangeEffect = () => { onCommandClick: () => openCreateActivity({ type: 'Task' }), }, ]); + }, [addToCommandMenu, setToIntitialCommandMenu, openCreateActivity]); + useEffect(() => { setTimeout(() => { eventTracker('pageview', { location: { @@ -198,20 +213,7 @@ export const PageChangeEffect = () => { }, }); }, 500); - }, [ - onboardingStatus, - navigate, - isMatchingLocation, - setHotkeyScope, - location, - previousLocation, - eventTracker, - workspaceFromInviteHashQuery, - enqueueSnackBar, - addToCommandMenu, - openCreateActivity, - setToIntitialCommandMenu, - ]); + }, [eventTracker, location.pathname]); return <>; }; diff --git a/front/src/hooks/useIsMatchingLocation.ts b/front/src/hooks/useIsMatchingLocation.ts index 6af6c2e1c..db7026ec0 100644 --- a/front/src/hooks/useIsMatchingLocation.ts +++ b/front/src/hooks/useIsMatchingLocation.ts @@ -1,3 +1,4 @@ +import { useCallback } from 'react'; import { matchPath, useLocation } from 'react-router-dom'; import { parse } from 'url'; @@ -6,11 +7,14 @@ import { AppBasePath } from '@/types/AppBasePath'; export const useIsMatchingLocation = () => { const location = useLocation(); - return (path: string, basePath?: AppBasePath) => { - const constructedPath = basePath - ? parse(`${basePath}/${path}`).pathname ?? '' - : path; + return useCallback( + (path: string, basePath?: AppBasePath) => { + const constructedPath = basePath + ? parse(`${basePath}/${path}`).pathname ?? '' + : path; - return !!matchPath(constructedPath, location.pathname); - }; + return !!matchPath(constructedPath, location.pathname); + }, + [location.pathname], + ); }; diff --git a/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts b/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts index bac83bd93..c37e26632 100644 --- a/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts +++ b/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts @@ -1,3 +1,4 @@ +import { useCallback } from 'react'; import { isNonEmptyString } from '@sniptt/guards'; import { useRecoilState, useRecoilValue } from 'recoil'; @@ -32,47 +33,55 @@ export const useOpenCreateActivityDrawer = () => { ); const [, setViewableActivityId] = useRecoilState(viewableActivityIdState); - return async ({ - type, - targetableEntities, - assigneeId, - }: { - type: ActivityType; - targetableEntities?: ActivityTargetableEntity[]; - assigneeId?: string; - }) => { - const targetableEntitiesWithRelations = targetableEntities - ? getTargetableEntitiesWithParents(targetableEntities) - : []; + return useCallback( + async ({ + type, + targetableEntities, + assigneeId, + }: { + type: ActivityType; + targetableEntities?: ActivityTargetableEntity[]; + assigneeId?: string; + }) => { + const targetableEntitiesWithRelations = targetableEntities + ? getTargetableEntitiesWithParents(targetableEntities) + : []; - const createdActivity = await createOneActivity?.({ - authorId: currentWorkspaceMember?.id, - assigneeId: - assigneeId ?? isNonEmptyString(currentWorkspaceMember?.id) - ? currentWorkspaceMember?.id - : undefined, - type: type, - }); + const createdActivity = await createOneActivity?.({ + authorId: currentWorkspaceMember?.id, + assigneeId: + assigneeId ?? isNonEmptyString(currentWorkspaceMember?.id) + ? currentWorkspaceMember?.id + : undefined, + type: type, + }); - if (!createdActivity) { - return; - } + if (!createdActivity) { + return; + } - await Promise.all( - targetableEntitiesWithRelations.map(async (targetableEntity) => { - await createOneActivityTarget?.({ - companyId: - targetableEntity.type === 'Company' ? targetableEntity.id : null, - personId: - targetableEntity.type === 'Person' ? targetableEntity.id : null, - activityId: createdActivity.id, - }); - }), - ); + await Promise.all( + targetableEntitiesWithRelations.map(async (targetableEntity) => { + await createOneActivityTarget?.({ + companyId: + targetableEntity.type === 'Company' ? targetableEntity.id : null, + personId: + targetableEntity.type === 'Person' ? targetableEntity.id : null, + activityId: createdActivity.id, + }); + }), + ); - setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); - setViewableActivityId(createdActivity.id); - setActivityTargetableEntityArray(targetableEntities ?? []); - openRightDrawer(RightDrawerPages.CreateActivity); - }; + setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); + setViewableActivityId(createdActivity.id); + setActivityTargetableEntityArray(targetableEntities ?? []); + openRightDrawer(RightDrawerPages.CreateActivity); + }, + [ + openRightDrawer, + setActivityTargetableEntityArray, + setHotkeyScope, + setViewableActivityId, + ], + ); }; diff --git a/front/src/modules/command-menu/hooks/useCommandMenu.ts b/front/src/modules/command-menu/hooks/useCommandMenu.ts index 00cee62bc..756415ed1 100644 --- a/front/src/modules/command-menu/hooks/useCommandMenu.ts +++ b/front/src/modules/command-menu/hooks/useCommandMenu.ts @@ -1,3 +1,4 @@ +import { useCallback } from 'react'; import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; @@ -38,9 +39,12 @@ export const useCommandMenu = () => { } }); - const addToCommandMenu = (addCommand: Command[]) => { - setCommands((prev) => [...prev, ...addCommand]); - }; + const addToCommandMenu = useCallback( + (addCommand: Command[]) => { + setCommands((prev) => [...prev, ...addCommand]); + }, + [setCommands], + ); const setToIntitialCommandMenu = () => { setCommands(commandMenuCommands); diff --git a/front/src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.tsx b/front/src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.tsx index 39002ca54..0731889e6 100644 --- a/front/src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.tsx +++ b/front/src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.tsx @@ -1,3 +1,4 @@ +import { useCallback } from 'react'; import { useRecoilCallback } from 'recoil'; import { v4 as uuidv4 } from 'uuid'; @@ -36,18 +37,19 @@ export const useSnackBar = () => { queue: [...prev.queue, newValue] as SnackBarOptions[], }; }), + [scopeId], ); - const enqueueSnackBar = ( - message: string, - options?: Omit, - ) => { - setSnackBarQueue({ - id: uuidv4(), - message, - ...options, - }); - }; + const enqueueSnackBar = useCallback( + (message: string, options?: Omit) => { + setSnackBarQueue({ + id: uuidv4(), + message, + ...options, + }); + }, + [setSnackBarQueue], + ); return { handleSnackBarClose, enqueueSnackBar }; };