-
Notifications
You must be signed in to change notification settings - Fork 235
fix: Page editor is not displayed when accessing directly in editor mode #10552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Page editor is not displayed when accessing directly in editor mode #10552
Conversation
| if (dynamicClassName != null) { | ||
| classNames.push(dynamicClassName); | ||
| } | ||
|
|
There was a problem hiding this comment.
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 に渡ってくる。
- index.page.tsx (NextPage)
- BasicLayout.tsx
- RawLayout.tsx
index.page.tsx から BasicLayout.tsx に useEditorModeClassName 由来の値を渡している。
growi/apps/app/src/pages/[[...path]]/index.page.tsx
Lines 182 to 189 in dc5424c
| const BasicLayoutWithEditor = ({ | |
| children, | |
| }: { | |
| children?: ReactNode; | |
| }): JSX.Element => { | |
| const editorModeClassName = useEditorModeClassName(); | |
| return <BasicLayout className={editorModeClassName}>{children}</BasicLayout>; | |
| }; |
EditorMode の初期値は determineEditorModeByHash により View が返却される
growi/apps/app/src/states/ui/editor/editor-mode.ts
Lines 14 to 76 in dc5424c
| 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, | |
| }; | |
| }; |
growi/apps/app/src/states/ui/editor/utils.ts
Lines 5 to 8 in dc5424c
| export const determineEditorModeByHash = (): EditorMode => { | |
| if (isServer()) { | |
| return EditorMode.View; | |
| } |
CSR 時は "Editor" となることで SSR/CSR でミスマッチが生じている。
Task
https://redmine.weseek.co.jp/issues/174985