Skip to content

Commit 819cc0b

Browse files
fix: BlockNoteViewEditor mismatched editable value (#2357)
* `BlockNoteViewEditor` editable fix * Implemented PR feedback * Added comment
1 parent 8ef3770 commit 819cc0b

2 files changed

Lines changed: 25 additions & 39 deletions

File tree

packages/react/src/editor/BlockNoteView.tsx

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import React, {
1010
ReactNode,
1111
Ref,
1212
useCallback,
13-
useEffect,
1413
useMemo,
1514
useState,
1615
} from "react";
@@ -141,10 +140,6 @@ function BlockNoteViewComponent<
141140
useEditorChange(onChange || emptyFn, editor);
142141
useEditorSelectionChange(onSelectionChange || emptyFn, editor);
143142

144-
useEffect(() => {
145-
editor.isEditable = editable !== false;
146-
}, [editable, editor]);
147-
148143
const setElementRenderer = useCallback(
149144
(ref: (typeof editor)["elementRenderer"]) => {
150145
editor.elementRenderer = ref;
@@ -170,6 +165,7 @@ function BlockNoteViewComponent<
170165
editorProps: {
171166
autoFocus,
172167
contentEditableProps,
168+
editable,
173169
},
174170
defaultUIProps: {
175171
formattingToolbar,
@@ -185,6 +181,7 @@ function BlockNoteViewComponent<
185181
}, [
186182
autoFocus,
187183
contentEditableProps,
184+
editable,
188185
formattingToolbar,
189186
linkToolbar,
190187
slashMenu,
@@ -202,7 +199,6 @@ function BlockNoteViewComponent<
202199
<BlockNoteViewContainer
203200
className={className}
204201
renderEditor={renderEditor}
205-
editable={editable}
206202
editorColorScheme={editorColorScheme}
207203
ref={ref}
208204
{...rest}
@@ -222,34 +218,26 @@ const BlockNoteViewContainer = React.forwardRef<
222218
HTMLDivElement,
223219
{
224220
renderEditor: boolean;
225-
editable?: boolean;
226221
editorColorScheme: "light" | "dark";
227222
children: ReactNode;
228223
} & Omit<
229224
HTMLAttributes<HTMLDivElement>,
230225
"onChange" | "onSelectionChange" | "children"
231226
>
232-
>(
233-
(
234-
{ className, renderEditor, editable, editorColorScheme, children, ...rest },
235-
ref,
236-
) => (
237-
<div
238-
className={mergeCSSClasses("bn-container", editorColorScheme, className)}
239-
data-color-scheme={editorColorScheme}
240-
{...rest}
241-
ref={ref}
242-
>
243-
{renderEditor ? (
244-
<BlockNoteViewEditor editable={editable}>
245-
{children}
246-
</BlockNoteViewEditor>
247-
) : (
248-
children
249-
)}
250-
</div>
251-
),
252-
);
227+
>(({ className, renderEditor, editorColorScheme, children, ...rest }, ref) => (
228+
<div
229+
className={mergeCSSClasses("bn-container", editorColorScheme, className)}
230+
data-color-scheme={editorColorScheme}
231+
{...rest}
232+
ref={ref}
233+
>
234+
{renderEditor ? (
235+
<BlockNoteViewEditor>{children}</BlockNoteViewEditor>
236+
) : (
237+
children
238+
)}
239+
</div>
240+
));
253241

254242
// https://fettblog.eu/typescript-react-generic-forward-refs/
255243
export const BlockNoteViewRaw = React.forwardRef(BlockNoteViewComponent) as <
@@ -269,10 +257,7 @@ export const BlockNoteViewRaw = React.forwardRef(BlockNoteViewComponent) as <
269257
* Renders the contentEditable editor itself (.bn-editor element) and the
270258
* default UI elements.
271259
*/
272-
export const BlockNoteViewEditor = (props: {
273-
editable?: boolean;
274-
children?: ReactNode;
275-
}) => {
260+
export const BlockNoteViewEditor = (props: { children?: ReactNode }) => {
276261
const ctx = useBlockNoteViewContext()!;
277262
const editor = useBlockNoteEditor();
278263

@@ -282,12 +267,12 @@ export const BlockNoteViewEditor = (props: {
282267

283268
const mount = useCallback(
284269
(element: HTMLElement | null) => {
285-
if (
286-
props.editable !== undefined &&
287-
props.editable !== editor.isEditable
288-
) {
289-
editor.isEditable = props.editable;
290-
}
270+
// Set editable state of the actual editor.
271+
// We need to re-mount the editor when changing `isEditable` as TipTap
272+
// removes the `tabIndex="0"` attribute we set (see
273+
// `BlockNoteEditor.ts`). Ideally though, this logic would exist in a
274+
// separate hook.
275+
editor.isEditable = ctx.editorProps.editable !== false;
291276
// Since we are not using TipTap's React Components, we need to set up the contentComponent it expects
292277
// This is a simple replacement for the state management that Tiptap does internally
293278
editor._tiptapEditor.contentComponent = portalManager;
@@ -297,7 +282,7 @@ export const BlockNoteViewEditor = (props: {
297282
editor.unmount();
298283
}
299284
},
300-
[editor, portalManager, props.editable],
285+
[ctx.editorProps.editable, editor, portalManager],
301286
);
302287

303288
return (

packages/react/src/editor/BlockNoteViewContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type BlockNoteViewContextValue = {
55
editorProps: {
66
autoFocus?: boolean;
77
contentEditableProps?: Record<string, any>;
8+
editable?: boolean;
89
};
910
defaultUIProps: BlockNoteDefaultUIProps;
1011
};

0 commit comments

Comments
 (0)