draft-js
draft-js copied to clipboard
Draft not compatible with React 17
It appears that Draft is not fully compatible with React 17. The selection state sometimes isn't updated correctly.
To reproduce:
- Check out the master branch of Draft JS
- In package.json, update the versions of react and react-dom to
"^17.0.1", and react-test-renderer to"^17.0.0" - Run
yarn installandyarn run build - Open the
rich.htmlexample in a browser - Enter two paragraphs of text, e.g.:
We provide the building blocks to enable the creation of a broad variety of rich text composition experiences, from basic text styles to embedded media.
Draft.js fits seamlessly into React applications, abstracting away the details of rendering, selection, and input behavior with a familiar declarative API.
- Select the word "seamlessly", and click the "B" icon twice to mark it as bold and unmark it again.
- Click outside the editor
- Select backwards from the end to the beginning, so that all text appears to be marked
- Click the "B" icon
Result: only the word "seamlessly" is marked as bold. Expected result: the whole text should be marked as bold.
I was wondering if any work is already being done within Facebook to make Draft compatible with React 17? I'd like to help, but I have to admit that I don't really know where to start with this. I suspect that it has to do with the changes to the event delegation system described in https://reactjs.org/blog/2020/10/20/react-v17.html#changes-to-event-delegation, but I'm not sure.
I am experiencing the same issue using React 17 and latest Draft-js. It seems like selection stops tracking events outside of viewport. If I start highlighting blocks and continue highlighting with my mouse outside of viewport, Selection loses highlighted text and once I attempt to toggle styles or block types it ends up only modifying the initial block.
https://codesandbox.io/s/formik-09x-draftjs-example-forked-0p9ce?file=/RichEditor.js:318-319

If this helps anyone you can patch this issue by detecting out of viewport mouse release and trigger event on the root element within viewport bounds.
const useOutOfBoundsSelectionRecovery = (inFocus: boolean) => {
useLayoutEffect(() => {
if (!inFocus) {
return
}
const handleOutsideMouseRelease = (e: MouseEvent) => {
const vw = Math.max(
document.documentElement.clientWidth || 0,
window.innerWidth || 0
)
const vh = Math.max(
document.documentElement.clientHeight || 0,
window.innerHeight || 0
)
const isOutOfBounds =
Math.min(e.offsetX, e.offsetY) < 0 || e.offsetX > vw || e.offsetY > vh
if (isOutOfBounds) {
const root = document.getElementById("root") as HTMLElement
const mouseEvent = new MouseEvent("mouseup", {
clientX: Math.min(vw, Math.max(0, e.clientX)),
clientY: Math.min(vh, Math.max(0, e.clientY))
})
root.dispatchEvent(mouseEvent)
}
}
document.addEventListener("mouseup", handleOutsideMouseRelease)
return () => {
document.removeEventListener("mouseup", handleOutsideMouseRelease)
}
}, [inFocus])
}
You can skip the inFocus check if you don't keep track of focus. Just run this hook within your Editor component.
For anyone coming to GitHub issues for "cursor jumping", "text not deleting", or "unable to select" issues, we had a series of occasional, hard to reproduce issues after upgrading to React 17. After finding this issue, we downgraded back to React 16. Our hypothesis is that they were all related to the event delegation issues highlighted above.
Is anyone running this with React 17 without any issues?
We would like to upgrade to React 17 because other packages are starting to depend on React 17 as well and DraftJS is the only one keeping us from upgrading.
I have exactly the same issue, any solution? React17 was release a year ago