Fix blank page layout after navigation (#17340)

Until now, it wasn’t possible to navigate between page layouts.
Dashboards don’t contain links to other dashboards. With record page
layouts, however, a page layout can now contain a link to another page
layout. If the user opens a record in the side panel and then clicks a
link to another record, the current page layout is replaced with the
page layout for the clicked record.

In this scenario, the `PageLayoutRenderer` component is not remounted.
As a result, the `isInitialized` state was not reset to `false`, and the
corresponding initialization `useEffect` was not triggered again.

All page layout states are component states bound to
`PageLayoutComponentInstanceContext`. For example, after navigating to
another record, `pageLayoutPersistedComponentState` was actually
`undefined` because the context's `instanceId` had changed.

Replacing the `isInitialized` state with a component state fixes the bug
and is consistent with the existing pattern of using component states to
store everything related to page layouts.

## Before


https://github.com/user-attachments/assets/24217145-51e5-49ef-8180-de62a6acfe10

## After


https://github.com/user-attachments/assets/e0ffe107-8fae-4f3a-9016-72c85bc735f4
This commit is contained in:
Baptiste Devessier
2026-01-22 17:52:56 +01:00
committed by GitHub
parent f11442953c
commit 3ef789dab4
2 changed files with 23 additions and 3 deletions
@@ -20,14 +20,16 @@ import { DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT_ID } from '@/page-layout/constants
import { usePageLayoutWithRelationWidgets } from '@/page-layout/hooks/usePageLayoutWithRelationWidgets';
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutIsInitializedComponentState } from '@/page-layout/states/pageLayoutIsInitializedComponentState';
import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
import { type PageLayout } from '@/page-layout/types/PageLayout';
import { convertPageLayoutToTabLayouts } from '@/page-layout/utils/convertPageLayoutToTabLayouts';
import { transformPageLayout } from '@/page-layout/utils/transformPageLayout';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useQuery } from '@apollo/client';
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@@ -65,7 +67,9 @@ export const PageLayoutInitializationQueryEffect = ({
pageLayoutId,
onInitialized,
}: PageLayoutInitializationQueryEffectProps) => {
const [isInitialized, setIsInitialized] = useState(false);
const [isInitialized, setIsInitialized] = useRecoilComponentState(
pageLayoutIsInitializedComponentState,
);
const isDefaultLayout =
pageLayoutId === DEFAULT_RECORD_PAGE_LAYOUT_ID ||
@@ -138,7 +142,13 @@ export const PageLayoutInitializationQueryEffect = ({
onInitialized?.(pageLayout);
setIsInitialized(true);
}
}, [initializePageLayout, isInitialized, pageLayout, onInitialized]);
}, [
initializePageLayout,
isInitialized,
pageLayout,
onInitialized,
setIsInitialized,
]);
return null;
};
@@ -0,0 +1,10 @@
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { PageLayoutComponentInstanceContext } from './contexts/PageLayoutComponentInstanceContext';
export const pageLayoutIsInitializedComponentState =
createComponentState<boolean>({
key: 'pageLayoutIsInitializedComponentState',
defaultValue: false,
componentInstanceContext: PageLayoutComponentInstanceContext,
});