caprica
caprica

Reputation: 4146

How to automatically set focus to a SlateJS editor inside a react-hook-form

I am building a custom SlateJS editor to use in a form, utilising the react-hook-form <Controller> component.

This mostly works, but two things (I suspect are related) do not:

  1. Focus activation via react-hook-form initialFocus, or setFocus from the form context hook
  2. Resetting the form value via the form hook reset() method

This is the controller that hooks up the react-hook-form component:

const CustomEditorController = () => {
    const { control } = useFormContext()

    return (
        <Controller
            name='editor'
            control={control}
            render={({ field }) => (
                <CustomEditor
                    ref={(el: any} => field.ref(el)}
                    name={field.name}
                    value={field.value}
                    onValueChange={field.onChange}
                />
            )}
        />
    )
}

The custom editor component looks like this:

const CustomEditor = React.forwardRef<any, TextEditorProps>(
    (name, value, onValueChange }, ref) => {
        const editor: MyEditor = useMemo(() => (withHistory(withReact(createEditor()))), [])

        useImperativeHandle(ref, () => ({
            focus: () => {
                console.log("set focus via imperative handle");
                ReactEditor.focus(editor);
            },
        }));

        return (
            <Slate
                editor={editor}
                initialValue={value}
                onValueChange={onValueChange}
            >
                <Editable
                    name={name}
                />
            </Slate>
        )
    }
)

With other components I have integrated with react-hook-forms, like a custom text input, you can use this ref property, and this all works perfectly - it sets focus at the right time, and resets the input value when reset() is invoked via the form hook.

But with this SlateJS editor, I can not see how I can use this ref, or otherwise how to propagate the focus/reset calls from the form to the editor.

I have found there is a ReactEditor.focus(editor) SlateJS API that can be used, but how to use that in this scenario, and what about reset() as well?

Upvotes: 1

Views: 717

Answers (1)

caprica
caprica

Reputation: 4146

In the CustomEditor code, explicitly setting focus via useImperativeHandle was the missing piece:

useImperativeHandle(ref, () => ({
  focus: () => {
    console.log("set focus via imperative handle");
    ReactEditor.focus(editor);
  },
}));

Fully working sandbox here https://codesandbox.io/p/sandbox/vigorous-gould-x3nwxg.

Upvotes: 2

Related Questions