Skip to content

Conversation

@miya
Copy link
Member

@miya miya commented Nov 28, 2025

@miya miya requested a review from yuki-takei November 28, 2025 08:44
@miya miya self-assigned this Nov 28, 2025
@miya miya changed the base branch from master to dev/7.4.x November 28, 2025 08:44
if (dynamicClassName != null) {
classNames.push(dynamicClassName);
}

Copy link
Member Author

@miya miya Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原因

#edit 付きの URL に直接アクセスした時に PageEditor が開かなかった原因は RawLayout の className が SSR / CSR で異なっていたことによる。

#edit 付きの URL に直接アクセスした時には下記の Warning が出ていた。

Warning

installHook.js:1 Warning: Prop `className` did not match. Server: "layout-root growi BasicLayout_grw-basic-layout__uEM3l " Client: "layout-root growi BasicLayout_grw-basic-layout__uEM3l editing builtin-editor"

props.className は以下の順序で RawLayout.tsx に渡ってくる。

  1. index.page.tsx (NextPage)
  2. BasicLayout.tsx
  3. RawLayout.tsx

index.page.tsx から BasicLayout.tsx に useEditorModeClassName 由来の値を渡している。

const BasicLayoutWithEditor = ({
children,
}: {
children?: ReactNode;
}): JSX.Element => {
const editorModeClassName = useEditorModeClassName();
return <BasicLayout className={editorModeClassName}>{children}</BasicLayout>;
};

EditorMode の初期値は determineEditorModeByHash により View が返却される

export const editorModeAtom = atom(
(get) => {
const baseMode = get(editorModeBaseAtom);
// If already initialized, return the current mode
if (baseMode !== null) {
return baseMode;
}
// Initialize from hash on first access
return determineEditorModeByHash();
},
(_get, set, newMode: EditorMode) => {
// Update URL hash when mode changes (client-side only)
if (!isServer()) {
const { pathname, search } = window.location;
const hash =
newMode === EditorMode.Editor
? EditorModeHash.Edit
: EditorModeHash.View;
window.history.replaceState(null, '', `${pathname}${search}${hash}`);
}
set(editorModeBaseAtom, newMode);
},
);
export const useEditorMode = (): UseEditorModeReturn => {
const isEditable = useIsEditable();
const [editorMode, setEditorModeRaw] = useAtom(editorModeAtom);
// Check if editor mode should be prevented
const preventModeEditor = !isEditable;
// Ensure View mode when editing is not allowed
const finalMode = preventModeEditor ? EditorMode.View : editorMode;
// Custom setter that respects permissions and updates hash
const setEditorMode = useCallback(
(newMode: EditorMode) => {
if (preventModeEditor && newMode === EditorMode.Editor) {
// If editing is not allowed, do nothing
return;
}
setEditorModeRaw(newMode);
},
[preventModeEditor, setEditorModeRaw],
);
const getClassNamesByEditorMode = useCallback(() => {
const classNames: string[] = [];
if (finalMode === EditorMode.Editor) {
classNames.push('editing', 'builtin-editor');
}
return classNames;
}, [finalMode]);
return {
editorMode: finalMode,
setEditorMode,
getClassNamesByEditorMode,
};
};

export const determineEditorModeByHash = (): EditorMode => {
if (isServer()) {
return EditorMode.View;
}

CSR 時は "Editor" となることで SSR/CSR でミスマッチが生じている。

@yuki-takei yuki-takei merged commit 9b040f4 into dev/7.4.x Dec 3, 2025
9 checks passed
@yuki-takei yuki-takei deleted the fix/174985-page-editor-is-not-displayed-when-accessing-directly-in-editor-mode branch December 3, 2025 10:57
@github-actions github-actions bot mentioned this pull request Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants