diff --git a/packages/slate-react/src/plugin/with-react.ts b/packages/slate-react/src/plugin/with-react.ts index 63ece1af0f..395f208ddb 100644 --- a/packages/slate-react/src/plugin/with-react.ts +++ b/packages/slate-react/src/plugin/with-react.ts @@ -349,13 +349,25 @@ export const withReact = ( } e.onChange = options => { - const onContextChange = EDITOR_TO_ON_CHANGE.get(e) - - if (onContextChange) { - onContextChange(options) - } + // COMPAT: React < 18 doesn't batch `setState` hook calls, which means + // that the children and selection can get out of sync for one render + // pass. So we have to use this unstable API to ensure it batches them. + // (2019/12/03) + // https://github.com/facebook/react/issues/14259#issuecomment-439702367 + const maybeBatchUpdates = + REACT_MAJOR_VERSION < 18 + ? ReactDOM.unstable_batchedUpdates + : (callback: () => void) => callback() + + maybeBatchUpdates(() => { + const onContextChange = EDITOR_TO_ON_CHANGE.get(e) + + if (onContextChange) { + onContextChange(options) + } - onChange(options) + onChange(options) + }) } return e