Remove recoil sync (#11569)
Recoil-sync was causing issues with Firefox, replacing it with a simpler mechanism to hydrate variables on page load --------- Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
This commit is contained in:
@ -9,35 +9,32 @@ import { i18n } from '@lingui/core';
|
||||
import { I18nProvider } from '@lingui/react';
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { RecoilURLSyncJSON } from 'recoil-sync';
|
||||
import { initialI18nActivate } from '~/utils/i18n/initialI18nActivate';
|
||||
import { IconsProvider } from 'twenty-ui/display';
|
||||
import { initialI18nActivate } from '~/utils/i18n/initialI18nActivate';
|
||||
|
||||
initialI18nActivate();
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<RecoilURLSyncJSON location={{ part: 'queryParams' }}>
|
||||
<AppErrorBoundary
|
||||
resetOnLocationChange={false}
|
||||
FallbackComponent={AppRootErrorFallback}
|
||||
>
|
||||
<I18nProvider i18n={i18n}>
|
||||
<RecoilDebugObserverEffect />
|
||||
<ApolloDevLogEffect />
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
<IconsProvider>
|
||||
<ExceptionHandlerProvider>
|
||||
<HelmetProvider>
|
||||
<AppRouter />
|
||||
</HelmetProvider>
|
||||
</ExceptionHandlerProvider>
|
||||
</IconsProvider>
|
||||
</SnackBarProviderScope>
|
||||
</I18nProvider>
|
||||
</AppErrorBoundary>
|
||||
</RecoilURLSyncJSON>
|
||||
<AppErrorBoundary
|
||||
resetOnLocationChange={false}
|
||||
FallbackComponent={AppRootErrorFallback}
|
||||
>
|
||||
<I18nProvider i18n={i18n}>
|
||||
<RecoilDebugObserverEffect />
|
||||
<ApolloDevLogEffect />
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
<IconsProvider>
|
||||
<ExceptionHandlerProvider>
|
||||
<HelmetProvider>
|
||||
<AppRouter />
|
||||
</HelmetProvider>
|
||||
</ExceptionHandlerProvider>
|
||||
</IconsProvider>
|
||||
</SnackBarProviderScope>
|
||||
</I18nProvider>
|
||||
</AppErrorBoundary>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@ -26,6 +26,7 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||
import { usePageChangeEffectNavigateLocation } from '~/hooks/usePageChangeEffectNavigateLocation';
|
||||
import { useInitializeQueryParamState } from '~/modules/app/hooks/useInitializeQueryParamState';
|
||||
|
||||
// TODO: break down into smaller functions and / or hooks
|
||||
// - moved usePageChangeEffectNavigateLocation into dedicated hook
|
||||
@ -44,6 +45,8 @@ export const PageChangeEffect = () => {
|
||||
|
||||
const eventTracker = useEventTracker();
|
||||
|
||||
const { initializeQueryParamState } = useInitializeQueryParamState();
|
||||
|
||||
//TODO: refactor useResetTableRowSelection hook to not throw when the argument `recordTableId` is an empty string
|
||||
// - replace CoreObjectNamePlural.Person
|
||||
const objectNamePlural =
|
||||
@ -64,10 +67,12 @@ export const PageChangeEffect = () => {
|
||||
}, [location, previousLocation, executeTasksOnAnyLocationChange]);
|
||||
|
||||
useEffect(() => {
|
||||
initializeQueryParamState();
|
||||
|
||||
if (isDefined(pageChangeEffectNavigateLocation)) {
|
||||
navigate(pageChangeEffectNavigateLocation);
|
||||
}
|
||||
}, [navigate, pageChangeEffectNavigateLocation]);
|
||||
}, [navigate, pageChangeEffectNavigateLocation, initializeQueryParamState]);
|
||||
|
||||
useEffect(() => {
|
||||
const isLeavingRecordIndexPage = !!matchPath(
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { isQueryParamInitializedState } from '@/app/states/isQueryParamInitializedState';
|
||||
import { billingCheckoutSessionState } from '@/auth/states/billingCheckoutSessionState';
|
||||
import { BillingCheckoutSession } from '@/auth/types/billingCheckoutSession.type';
|
||||
import { BILLING_CHECKOUT_SESSION_DEFAULT_VALUE } from '@/billing/constants/BillingCheckoutSessionDefaultValue';
|
||||
|
||||
// Initialize state that are hydrated from query parameters
|
||||
// We used to use recoil-sync to do this, but it was causing issues with Firefox
|
||||
export const useInitializeQueryParamState = () => {
|
||||
const initializeQueryParamState = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
() => {
|
||||
const isInitialized = snapshot
|
||||
.getLoadable(isQueryParamInitializedState)
|
||||
.getValue();
|
||||
|
||||
if (!isInitialized) {
|
||||
const handlers = {
|
||||
billingCheckoutSession: (value: string) => {
|
||||
try {
|
||||
const parsedValue = JSON.parse(decodeURIComponent(value));
|
||||
|
||||
if (
|
||||
typeof parsedValue === 'object' &&
|
||||
parsedValue !== null &&
|
||||
'plan' in parsedValue &&
|
||||
'interval' in parsedValue &&
|
||||
'requirePaymentMethod' in parsedValue
|
||||
) {
|
||||
set(
|
||||
billingCheckoutSessionState,
|
||||
parsedValue as BillingCheckoutSession,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
'Failed to parse billingCheckoutSession from URL',
|
||||
error,
|
||||
);
|
||||
set(
|
||||
billingCheckoutSessionState,
|
||||
BILLING_CHECKOUT_SESSION_DEFAULT_VALUE,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const queryParams = new URLSearchParams(window.location.search);
|
||||
|
||||
for (const [paramName, handler] of Object.entries(handlers)) {
|
||||
const value = queryParams.get(paramName);
|
||||
if (value !== null) {
|
||||
handler(value);
|
||||
}
|
||||
}
|
||||
|
||||
set(isQueryParamInitializedState, true);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return { initializeQueryParamState };
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const isQueryParamInitializedState = createState<boolean>({
|
||||
key: 'isQueryParamInitializedState',
|
||||
defaultValue: false,
|
||||
});
|
||||
Reference in New Issue
Block a user