Open pubuzhixing8 opened 4 years ago
chrome browser think the text should follow previous node when cursor is at end edge for bold text, but slate think it should follow next node
At the first glance, I thought this problem was caused by the Slate's internal selection function.
In Safari, the editor's selection
's path
and anchor
is correct after hitting <LeftArrow>
that triggers the onDOMSelectionChange
.
// editor's selection in Safari
{anchor: {path: [0, 1], offset: 4}, focus: {path: [0, 1], offset: 4}}
// editor's selection in Chrome
{anchor: {path: [0, 2], offset: 0}, focus: {path: [0, 2], offset: 0}}
This is because window.getSelection()
has returned different result in Chrome and Safari.
As the selection for Editor.insertText
is not correct in Chrome, my workaround is to use setTimeout
to wait until the selection is updated by onDOMSelectionChange
.
// slate-react/src/components/editable.tsx
...
if (!IS_SAFARI && !IS_FIREFOX && event.data) {
const data = event.data
// insert text in next event cycle
setTimeout(() => {
const { selection } = editor
if (selection) {
Transforms.setSelection(editor, {
anchor: {
path: selection.anchor.path,
offset: selection.anchor.offset - data.length,
},
focus: {
path: selection.anchor.path,
offset: selection.anchor.offset - data.length,
},
})
Editor.insertText(editor, data)
}
})
...
And it works. I also combined this with #3626 to fix cursor misplacement in Safari.
At the first glance, I thought this problem was caused by the Slate's internal selection function. In Safari, the editor's
selection
'spath
andanchor
is correct after hitting<LeftArrow>
that triggers theonDOMSelectionChange
.// editor's selection in Safari {anchor: {path: [0, 1], offset: 4}, focus: {path: [0, 1], offset: 4}} // editor's selection in Chrome {anchor: {path: [0, 2], offset: 0}, focus: {path: [0, 2], offset: 0}}
This is because
window.getSelection()
has returned different result in Chrome and Safari.As the selection for
Editor.insertText
is not correct in Chrome, my workaround is to usesetTimeout
to wait until the selection is updated byonDOMSelectionChange
.// slate-react/src/components/editable.tsx ... if (!IS_SAFARI && !IS_FIREFOX && event.data) { const data = event.data // insert text in next event cycle setTimeout(() => { const { selection } = editor if (selection) { Transforms.setSelection(editor, { anchor: { path: selection.anchor.path, offset: selection.anchor.offset - data.length, }, focus: { path: selection.anchor.path, offset: selection.anchor.offset - data.length, }, }) Editor.insertText(editor, data) } }) ...
And it works. I also combined this with #3626 to fix cursor misplacement in Safari.
你好,这个方法确实能够解决这个中文输入重复的问题,可是在一段普通文本中先点击加粗,然后再输入文本,此时输入是否会因此导致输入为普通不带格式的文本呢?
It's contenteditable problem in React. You can insert a '\ufeff' after add or remove mark when cursor is collapsed
@wangqs1990 I write the slate editor by angular ,same problem, so this is a compatibility issue for Chrome
I get this behavior too, when using Swiftkey keyboard on Android. Other keyboards works fine.
In my opinion, this is caused by react
reused the previous span
and didn't update it's value. Here is the exactly reason:
span1
), the added text will be added to current span
(span1
) directly because of span's editable=true
. However the slate element(e.g.element1
) , current span associated with, didn't change anything!onCompositionEnd
,slate-react
will create a new Text node with the event's data.And then slate
will call editor.onChange
to start the react
rerender procedure.react
rerendering, react
think element1
didn't change, so react reuse the span1 and no need do anything. As the result, react create the new span(e.g.span2
) for element2
and remain span1
(assocated with element1
).
After all you will see the repeat render.I also meet the problem before, to simplify this problem ,I tried to tell react
don't reuse the decorated span
,so I tried this and run away from the problem.
const createAlwaysNewComponent = () => ({ attributes, children }) => (
<span
{...attributes}
css={css`
color: var(--theme-color-text-lighten, #33333380);
`}
>
{children}
</span>
);
const DecoratedSpan = ({ attributes, children, leaf }) => {
const AlwaysNew = createAlwaysNewComponent();
return <AlwaysNew attributes={attributes}>{children}</AlwaysNew>;
};
在chrome浏览器上,这大概率是由于react
复用之前的span
元素导致的。具体过程为:
1.在decorated的节点span1
后键入中文字符,由于editable=ture
的效果,实际的文本会直接增加在当前span元素内部。注意,此时,与之对应的slate element
并没有发生任何变化。
2.在确定输入后,slate
通过onCompositionEnd
事件知道键入内容并创立了一个新的span2
,并将更新内容同步到slate value
上。
3.根据react框架,span1
对应的slate element
并没有发生变化,故react
不会更新span1
(这导致前一段文本没有删除),而span2
作为新增节点,react创建并绘制了新的节点。
综上,这导致了重复文本现象。
@ncqwer 试了还是不行啊~
Do you want to request a feature or report a bug?
Bug
What's the current behavior?
repeat rendering input text(first text is rendered by browser default action, last text is rendered by slate)
just heppen when user move cursor from right to left by arrowLeft https://www.slatejs.org/examples/richtext Slate: 0.58.1 Browser: Chrome OS: Mac
What's the expected behavior?
prevent browser default action.