1

I know there is an AutoFocusPlugin in @lexical/react, but I can't seem to get it to work properly on initial render.

Take the following code (which seems to be matching the current implementation of AutoFocusPlugin.js) - sandbox here :

import React, { FC, useLayoutEffect } from "react";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";

import LexicalComposer from "@lexical/react/LexicalComposer";
import LexicalPlainTextPlugin from "@lexical/react/LexicalPlainTextPlugin";
import LexicalContentEditable from "@lexical/react/LexicalContentEditable";

const AutofocusPlugin = () => {
  const [editor] = useLexicalComposerContext();

  useLayoutEffect(() => {
    editor.focus();
  }, [editor]);

  return null;
};

export const MyEditor = () => {
  return (
    <LexicalComposer initialConfig={{ onError: () => null }}>
      <LexicalPlainTextPlugin
        contentEditable={<LexicalContentEditable />}
        placeholder={null}
      />
      <AutofocusPlugin />
    </LexicalComposer>
  );
};

I would expect the editor to initialize focused, but it does not.

Deferring the focus call to the async stack seems to solve this inside the sandbox:

useLayoutEffect(() => {
  setTimeout(() => editor.focus(), 0);
}, [editor]);

but does not reliably work in Cypress/Storybook for me.

So what am I doing wrong?

Michal Kurz
  • 1,592
  • 13
  • 41

1 Answers1

0

As of lexical version 0.6.0, the lexical editor will not process the callbackFn in editor.focus() if there are no contents in the editor. see line 839 of: https://github.com/facebook/lexical/blob/main/packages/lexical/src/LexicalEditor.ts:

focus(callbackFn?: () => void, options: EditorFocusOptions = {}): void {...}

What I did was add a paragraph node if the root is empty on the initial editor state. Then the AutoFocusPlugin will work without issue:

const initialConfig = {
     ...
    onError: error => {
       throw error;
    },
    editorState: editor => {
    // For autoFocus to work, the editor needs to have a node present in the root.
       const root = $getRoot();
       if (root.isEmpty()) {
           const paragraph = $createParagraphNode();
           root.append(paragraph);
       }
    },
};