Skip to content
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

Cursor set to the end of text after each update #2216

Closed
1 of 2 tasks
nnurmano opened this issue Dec 1, 2021 · 14 comments
Closed
1 of 2 tasks

Cursor set to the end of text after each update #2216

nnurmano opened this issue Dec 1, 2021 · 14 comments
Labels
Type: Bug The issue or pullrequest is related to a bug

Comments

@nnurmano
Copy link

nnurmano commented Dec 1, 2021

What’s the bug you are facing?

I updated TipTap to the latest version and now the cursor sets to the end of the text whenever I update.
Here are the details:

export const Editor = ({content, onChange, pad = "none", readOnly}) => {
	let editor = useEditor({
		content: content,
		onUpdate({editor}) {
			onChange(editor.getHTML());
		},
		editable: readOnly,
		extensions: [
			Highlight,
			Placeholder,
			StarterKit,
		],
		parseOptions: {
			preserveWhitespace: "full"
		}
	});

	useEffect(() => {
		if (!editor) return;

		editor.commands.setContent(content,
			false, {
				preserveWhitespace: "full"
			});
	}, [editor, content]);

	return (
		<Box pad={pad} gap="small">
			{!readOnly && <MenuBar editor={editor}/>}
			<EditorContent
				editor={editor}
			/>
		</Box>);
};
<Editor
  {...this.props}
  content={post.description || ""}
  onChange={(value) => this.setState({
	  post: {
		  ...this.state.post,
		  description: value
	  },
	  validationErrors: {}
  })}
  pad="small"
  placeholder="Placeholder"/>

How can we reproduce the bug on our side?

I guess yes,
Here are the version details
"@tiptap/extension-highlight": "^2.0.0-beta.30",
"@tiptap/extension-placeholder": "^2.0.0-beta.44",
"@tiptap/react": "^2.0.0-beta.95",
"@tiptap/starter-kit": "^2.0.0-beta.145",

Can you provide a CodeSandbox?

I shall try

What did you expect to happen?

The cursor should stay where it is

Anything to add? (optional)

No response

Did you update your dependencies?

  • Yes, I’ve updated my dependencies to use the latest version of all packages.

Are you sponsoring us?

  • Yes, I’m a sponsor. 💖
@nnurmano nnurmano added the Type: Bug The issue or pullrequest is related to a bug label Dec 1, 2021
@philippkuehn
Copy link
Contributor

I can’t reproduce this. Not sure if it has something to do with editor.commands.setContent in your code because on setContent the cursor is set to the end. Provide a reproducable codesandbox and feel free to reopen.

@jonsherrard
Copy link

@nomadus I have the same issue, did you ever fix this?

@nnurmano
Copy link
Author

nnurmano commented Apr 13, 2022

Yes, I fixed, but I don't remember what exactly I did. Here is the latest code, which is different from the original one, maybe it will help?

	useEffect(() => {
		if (!editor) return;
		let {from, to} = editor.state.selection;
		editor.commands.setContent(content,
			false, {
				preserveWhitespace: "full"
			});
		editor.commands.setTextSelection({from, to});
	}, [editor, content]);

@jonsherrard
Copy link

you absolute beauty! This should be in the docs for people who are using the "controlled component" paradigm with React.

Thank you so much for sharing!

@nebosite
Copy link

Yes, I fixed, but I don't remember what exactly I did. Here is the latest code, which is different from the original one, maybe it will help?

YES! thanks!

@nullpaper
Copy link

Except this still needs a "magic-number" throttle/debounce because at fast enough input rates your render loop still gets out of sync. Your magic-number will vary based on the performance of your device and your time to render, but although this approach goes a long way to addressing the problem, it still gets overwhelmed at the extreme. It's not a fix.

@Opcode3
Copy link

Opcode3 commented Jun 5, 2023

Brother, you are a life saver... Thanks for the code snippet

@Goondrious
Copy link

Fix provided by @nnurmano works (ty!), but @nullpaper brings up a good point. Maybe there's a better way to support controlling the editor content. I searched around and couldn't find anything.

Can this issue be re-opened? Or is there a more generic "react responsivity/control" issue or solution?

@jonsherrard
Copy link

@porkopek
Copy link

Instead of using setContent, you can use insertContent, that does not replace the whole content, just insert the new content and doesn't move the cursor at the end of the content, just at the end of insertion.

And you don't need to use the component in a "controlled" way at all. You can just update the state on blur, for example. It's much faster and you don't need to debounce it.

@dbonissone
Copy link

Hi Guys,

The solution you proposed works but has a limitation: if you change the value outside the component and the value in the editor is not empty, it doesn't update.

The problem, as you mentioned, is that setContent sets the cursor to the bottom, but it shouldn't enter that function because there's a check above it:

const isSame = editor.getHTML() === newValue;
if (isSame) {
    return;
}

I wondered why it wasn't entering the if statement, so I investigated and discovered that getHTML() converts special characters while in newValue I found values like &Ugrave, &#140, etc. To correct this error, you need to replicate what getHTML() does. So the solution I found is this:

const div = document.createElement('div');
div.innerHTML = newValue;
const isSame = editor.getHTML() === div.innerHTML;
if (isSame) {
    return;
}
editor.commands.setContent(newValue, false);

That's why the problem doesn't always occur.
In the end, it notes that the value is the same and doesn't enter the setContent.

@bastiengrignon
Copy link

Yes, I fixed, but I don't remember what exactly I did. Here is the latest code, which is different from the original one, maybe it will help?

This code helped me a lot but there is still an issue when using ordered list or bullet list it's not working as expected ! Id doesn't insert a number or a bullet but some kind of line break !

Do you have an idea to fix this or why this his happening ?

@vashu0804
Copy link

Yes, I fixed, but I don't remember what exactly I did. Here is the latest code, which is different from the original one, maybe it will help?

	useEffect(() => {
		if (!editor) return;
		let {from, to} = editor.state.selection;
		editor.commands.setContent(content,
			false, {
				preserveWhitespace: "full"
			});
		editor.commands.setTextSelection({from, to});
	}, [editor, content]);

Hey man, this is insane, it helped me fixing the issue in my case. Thanks:))

@payamfakoorziba
Copy link

Yes, I fixed, but I don't remember what exactly I did. Here is the latest code, which is different from the original one, maybe it will help?

	useEffect(() => {
		if (!editor) return;
		let {from, to} = editor.state.selection;
		editor.commands.setContent(content,
			false, {
				preserveWhitespace: "full"
			});
		editor.commands.setTextSelection({from, to});
	}, [editor, content]);

Thank you so much! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug The issue or pullrequest is related to a bug
Projects
None yet
Development

No branches or pull requests