diff --git a/front/src/modules/analytics/hooks/useTrackPageView.ts b/front/src/modules/analytics/hooks/useTrackPageView.ts index 9d68045442..38af8303f3 100644 --- a/front/src/modules/analytics/hooks/useTrackPageView.ts +++ b/front/src/modules/analytics/hooks/useTrackPageView.ts @@ -1,17 +1,26 @@ import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; +import usePrevious from '@/utils/hooks/usePrevious'; + import { useEventTracker } from './useEventTracker'; export function useTrackPageView() { const location = useLocation(); + const previousLocation = usePrevious(location); const eventTracker = useEventTracker(); useEffect(() => { - eventTracker('pageview', { - location: { - pathname: location.pathname, - }, - }); - }, [location, eventTracker]); + // Avoid lot of pageview events enven if the location is the same + if ( + !previousLocation?.pathname || + previousLocation?.pathname !== location.pathname + ) { + eventTracker('pageview', { + location: { + pathname: location.pathname, + }, + }); + } + }, [location, eventTracker, previousLocation?.pathname]); } diff --git a/front/src/modules/apollo/hooks/useApolloFactory.ts b/front/src/modules/apollo/hooks/useApolloFactory.ts index b3b8574657..907600c64c 100644 --- a/front/src/modules/apollo/hooks/useApolloFactory.ts +++ b/front/src/modules/apollo/hooks/useApolloFactory.ts @@ -1,9 +1,10 @@ -import { useEffect, useMemo, useRef } from 'react'; +import { useMemo, useRef } from 'react'; import { InMemoryCache, NormalizedCacheObject } from '@apollo/client'; import { useRecoilState } from 'recoil'; import { tokenPairState } from '@/auth/states/tokenPairState'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; +import { useUpdateEffect } from '@/utils/hooks/useUpdateEffect'; import { CommentThreadTarget } from '~/generated/graphql'; import { ApolloFactory } from '../services/apollo.factory'; @@ -54,7 +55,7 @@ export function useApolloFactory() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [setTokenPair, isDebugMode]); - useEffect(() => { + useUpdateEffect(() => { if (apolloRef.current) { apolloRef.current.updateTokenPair(tokenPair); } diff --git a/front/src/modules/auth/states/isMockModeState.ts b/front/src/modules/auth/states/isMockModeState.ts deleted file mode 100644 index 3d29e5ce39..0000000000 --- a/front/src/modules/auth/states/isMockModeState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atom } from 'recoil'; - -export const isMockModeState = atom({ - key: 'isMockModeState', - default: false, -}); diff --git a/front/src/modules/ui/layout/AuthLayout.tsx b/front/src/modules/ui/layout/AuthLayout.tsx index 04becd3b68..bd7d2661cd 100644 --- a/front/src/modules/ui/layout/AuthLayout.tsx +++ b/front/src/modules/ui/layout/AuthLayout.tsx @@ -1,14 +1,9 @@ -import { useRecoilValue } from 'recoil'; - -import { isMockModeState } from '@/auth/states/isMockModeState'; -import { Companies } from '~/pages/companies/Companies'; import { CompaniesMockMode } from '~/pages/companies/CompaniesMockMode'; export function AuthLayout({ children }: React.PropsWithChildren) { - const isMockMode = useRecoilValue(isMockModeState); return ( <> - {isMockMode ? : } + {children} ); diff --git a/front/src/modules/utils/hooks/useFirstMountState.ts b/front/src/modules/utils/hooks/useFirstMountState.ts new file mode 100644 index 0000000000..cf210622a2 --- /dev/null +++ b/front/src/modules/utils/hooks/useFirstMountState.ts @@ -0,0 +1,13 @@ +import { useRef } from 'react'; + +export function useFirstMountState(): boolean { + const isFirst = useRef(true); + + if (isFirst.current) { + isFirst.current = false; + + return true; + } + + return isFirst.current; +} diff --git a/front/src/modules/utils/hooks/usePrevious.ts b/front/src/modules/utils/hooks/usePrevious.ts new file mode 100644 index 0000000000..a5233144ca --- /dev/null +++ b/front/src/modules/utils/hooks/usePrevious.ts @@ -0,0 +1,11 @@ +import { useEffect, useRef } from 'react'; + +export default function usePrevious(state: T): T | undefined { + const ref = useRef(); + + useEffect(() => { + ref.current = state; + }); + + return ref.current; +} diff --git a/front/src/modules/utils/hooks/useUpdateEffect.ts b/front/src/modules/utils/hooks/useUpdateEffect.ts new file mode 100644 index 0000000000..c8b5b41c27 --- /dev/null +++ b/front/src/modules/utils/hooks/useUpdateEffect.ts @@ -0,0 +1,14 @@ +import { DependencyList, EffectCallback, useEffect } from 'react'; + +import { useFirstMountState } from './useFirstMountState'; + +export function useUpdateEffect(effect: EffectCallback, deps?: DependencyList) { + const isFirst = useFirstMountState(); + + useEffect(() => { + if (!isFirst) { + return effect(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps); +} diff --git a/front/src/pages/auth/CreateProfile.tsx b/front/src/pages/auth/CreateProfile.tsx index 6964892fa3..11bd770b34 100644 --- a/front/src/pages/auth/CreateProfile.tsx +++ b/front/src/pages/auth/CreateProfile.tsx @@ -9,7 +9,6 @@ import { SubTitle } from '@/auth/components/ui/SubTitle'; import { Title } from '@/auth/components/ui/Title'; import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; import { currentUserState } from '@/auth/states/currentUserState'; -import { isMockModeState } from '@/auth/states/isMockModeState'; import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys'; import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope'; @@ -39,7 +38,6 @@ const StyledButtonContainer = styled.div` export function CreateProfile() { const navigate = useNavigate(); - const [, setMockMode] = useRecoilState(isMockModeState); const onboardingStatus = useOnboardingStatus(); const [currentUser] = useRecoilState(currentUserState); @@ -93,11 +91,10 @@ export function CreateProfile() { ); useEffect(() => { - setMockMode(true); if (onboardingStatus !== OnboardingStatus.OngoingProfileCreation) { navigate('/'); } - }, [onboardingStatus, navigate, setMockMode]); + }, [onboardingStatus, navigate]); return ( <> diff --git a/front/src/pages/auth/CreateWorkspace.tsx b/front/src/pages/auth/CreateWorkspace.tsx index 68bef6b3bc..146f705b2a 100644 --- a/front/src/pages/auth/CreateWorkspace.tsx +++ b/front/src/pages/auth/CreateWorkspace.tsx @@ -2,12 +2,10 @@ import { useCallback, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; -import { useRecoilState } from 'recoil'; import { SubTitle } from '@/auth/components/ui/SubTitle'; import { Title } from '@/auth/components/ui/Title'; import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; -import { isMockModeState } from '@/auth/states/isMockModeState'; import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys'; import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope'; @@ -36,7 +34,6 @@ const StyledButtonContainer = styled.div` `; export function CreateWorkspace() { - const [, setMockMode] = useRecoilState(isMockModeState); const navigate = useNavigate(); const onboardingStatus = useOnboardingStatus(); @@ -82,11 +79,10 @@ export function CreateWorkspace() { ); useEffect(() => { - setMockMode(true); if (onboardingStatus !== OnboardingStatus.OngoingWorkspaceCreation) { navigate('/auth/create/profile'); } - }, [onboardingStatus, navigate, setMockMode]); + }, [onboardingStatus, navigate]); return ( <> diff --git a/front/src/pages/auth/Index.tsx b/front/src/pages/auth/Index.tsx index f19120edec..f0fe3d1974 100644 --- a/front/src/pages/auth/Index.tsx +++ b/front/src/pages/auth/Index.tsx @@ -10,7 +10,6 @@ import { HorizontalSeparator } from '@/auth/components/ui/HorizontalSeparator'; import { Logo } from '@/auth/components/ui/Logo'; import { Title } from '@/auth/components/ui/Title'; import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState'; -import { isMockModeState } from '@/auth/states/isMockModeState'; import { authProvidersState } from '@/client-config/states/authProvidersState'; import { isDemoModeState } from '@/client-config/states/isDemoModeState'; import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys'; @@ -34,7 +33,6 @@ const StyledFooterNote = styled(FooterNote)` export function Index() { const navigate = useNavigate(); const theme = useTheme(); - const [, setMockMode] = useRecoilState(isMockModeState); const [authProviders] = useRecoilState(authProvidersState); const [demoMode] = useRecoilState(isDemoModeState); @@ -67,9 +65,8 @@ export function Index() { ); useEffect(() => { - setMockMode(true); setAuthFlowUserEmail(demoMode ? 'tim@apple.dev' : ''); - }, [navigate, setMockMode, setAuthFlowUserEmail, demoMode]); + }, [navigate, setAuthFlowUserEmail, demoMode]); return ( <> diff --git a/front/src/pages/auth/PasswordLogin.tsx b/front/src/pages/auth/PasswordLogin.tsx index 1a23939e82..896737e47d 100644 --- a/front/src/pages/auth/PasswordLogin.tsx +++ b/front/src/pages/auth/PasswordLogin.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; @@ -9,7 +9,6 @@ import { SubTitle } from '@/auth/components/ui/SubTitle'; import { Title } from '@/auth/components/ui/Title'; import { useAuth } from '@/auth/hooks/useAuth'; import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState'; -import { isMockModeState } from '@/auth/states/isMockModeState'; import { isDemoModeState } from '@/client-config/states/isDemoModeState'; import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys'; import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope'; @@ -51,12 +50,11 @@ const StyledErrorContainer = styled.div` export function PasswordLogin() { const navigate = useNavigate(); - const [isDemoMode] = useRecoilState(isDemoModeState); + const [isDemoMode] = useRecoilState(isDemoModeState); const [authFlowUserEmail, setAuthFlowUserEmail] = useRecoilState( authFlowUserEmailState, ); - const [, setMockMode] = useRecoilState(isMockModeState); const [internalPassword, setInternalPassword] = useState( isDemoMode ? 'Applecar2025' : '', ); @@ -69,15 +67,10 @@ export function PasswordLogin() { }, }); - useEffect(() => { - setMockMode(true); - }, [setMockMode]); - const workspaceInviteHash = useParams().workspaceInviteHash; const handleSubmit = useCallback(async () => { try { - setMockMode(false); if (data?.checkUserExists.exists) { await login(authFlowUserEmail, internalPassword); } else { @@ -101,7 +94,6 @@ export function PasswordLogin() { signUpToWorkspace, authFlowUserEmail, internalPassword, - setMockMode, navigate, data?.checkUserExists.exists, diff --git a/front/src/providers/user/UserProvider.tsx b/front/src/providers/user/UserProvider.tsx index e4ccfb9fe8..3cbf66b46c 100644 --- a/front/src/providers/user/UserProvider.tsx +++ b/front/src/providers/user/UserProvider.tsx @@ -1,14 +1,20 @@ import { useEffect, useState } from 'react'; import { useRecoilState } from 'recoil'; +import { useIsLogged } from '@/auth/hooks/useIsLogged'; import { currentUserState } from '@/auth/states/currentUserState'; import { useGetCurrentUserQuery } from '~/generated/graphql'; export function UserProvider({ children }: React.PropsWithChildren) { const [, setCurrentUser] = useRecoilState(currentUserState); - const { data, loading } = useGetCurrentUserQuery(); const [isLoading, setIsLoading] = useState(true); + const isLogged = useIsLogged(); + + const { data, loading } = useGetCurrentUserQuery({ + skip: !isLogged, + }); + useEffect(() => { if (!loading) { setIsLoading(false);