ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.61k stars 3.23k forks source link

Focusing an editor either freezes or doesn't work #4495

Open sarahdayan opened 3 years ago

sarahdayan commented 3 years ago

Description Hi! I'm using Slate and Slate React to build a Notion-like editor. In Notion, hitting Enter creates a new independent block, which I'm recreating by having as many parallel Slate editors as I have blocks.

When creating a new block upon hitting Enter, focus should move to the newly created block. To do so, I'm tracking which block should receive focus (by id) in a state. When adding a new block, I mutate this state. I also have an effect in each editor which calls ReactEditor.focus on the local editor when the block should receive focus. Weirdly, this doesn't work smoothly: every other time, the block doesn't get the focus, sometimes the cursor freezes, etc.

I know imperative focus can get trippy and conflict with the browser's native focus management, so I tried scheduling the call using setTimeout and requestAnimationFrame, but it doesn't change anything.

Recording

https://user-images.githubusercontent.com/5370675/132418973-1f5781c7-bcab-419b-b75b-05e6b04edf0b.mov

Sandbox

https://codesandbox.io/s/smoosh-cherry-kt7he?file=/src/App.jsx

Steps To reproduce the behavior:

  1. Focus any of the blocks.
  2. Hit Enter, see newly created block.
  3. Try typing, it probably won't work.
  4. Hit Enter again, see newly created block.
  5. Try typing, it might work this time.

I've added each block's id and I display the current ID at the bottom so you can see how the state is in sync. It's not an issue of the wrong block (or no block) receiving focus.

Expectation

I would expect the new block to receive focus when created, so that I can continue typing and have my text in the new block right after having hit Enter.

Environment

I'm happy to help resolving this issue and taking care of the pull request myself if necessary. However, I'd like to clarify what might be going on first, and make sure it's not coming from improper usage.

Ronbb commented 3 years ago

It works fine:

ReactEditor.focus(editor)
Transforms.select(editor, [0]);

But I dont know why :(

sarahdayan commented 3 years ago

@Ronbb Indeed! The only issue is that it selects the whole content of the initial block, which is undesirable behavior. Later on I'll need to remove blocks and focus the nearest neightbor, which might have content in it, so I can't even apply conditional behavior that selects only when the block is empty.

advissor commented 1 year ago

@Ronbb

Thanks mate! It did work for me as well. Spent few hours of fighting with "this is no a leaf node:. Probably, because there was a non slate tracked html element i clicked after rendering the block. Hence, it needed to refocus

Mixed it with findpath to focus on current div in render element and selecting it

     const pathNode = ReactEditor.findPath(editor, element);
     ReactEditor.focus(editor)
     Transforms.select(editor,  pathToNode);