diff --git a/.changeset/five-emus-roll.md b/.changeset/five-emus-roll.md new file mode 100644 index 000000000..e08580be9 --- /dev/null +++ b/.changeset/five-emus-roll.md @@ -0,0 +1,5 @@ +--- +'slate-react': patch +--- + +fix useFocused hook in react >= 17 diff --git a/packages/slate-react/src/components/slate.tsx b/packages/slate-react/src/components/slate.tsx index a96318484..7d157ee8a 100644 --- a/packages/slate-react/src/components/slate.tsx +++ b/packages/slate-react/src/components/slate.tsx @@ -9,6 +9,7 @@ import { SlateSelectorContext, } from '../hooks/use-slate-selector' import { EDITOR_TO_ON_CHANGE } from '../utils/weak-maps' +import { IS_REACT_VERSION_17_OR_ABOVE } from '../utils/environment' import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect' /** @@ -73,16 +74,23 @@ export const Slate = (props: { useIsomorphicLayoutEffect(() => { const fn = () => setIsFocused(ReactEditor.isFocused(editor)) - document.addEventListener('focus', fn, true) - return () => document.removeEventListener('focus', fn, true) - }, []) - - useIsomorphicLayoutEffect(() => { - const fn = () => setIsFocused(ReactEditor.isFocused(editor)) - document.addEventListener('blur', fn, true) - return () => { - document.removeEventListener('focus', fn, true) - document.removeEventListener('blur', fn, true) + if (IS_REACT_VERSION_17_OR_ABOVE) { + // In React >= 17 onFocus and onBlur listen to the focusin and focusout events during the bubbling phase. + // Therefore in order for 's handlers to run first, which is necessary for ReactEditor.isFocused(editor) + // to return the correct value, we have to listen to the focusin and focusout events without useCapture here. + document.addEventListener('focusin', fn) + document.addEventListener('focusout', fn) + return () => { + document.removeEventListener('focusin', fn) + document.removeEventListener('focusout', fn) + } + } else { + document.addEventListener('focus', fn, true) + document.addEventListener('blur', fn, true) + return () => { + document.removeEventListener('focus', fn, true) + document.removeEventListener('blur', fn, true) + } } }, []) diff --git a/packages/slate-react/src/utils/environment.ts b/packages/slate-react/src/utils/environment.ts index 7f78f135b..663572677 100644 --- a/packages/slate-react/src/utils/environment.ts +++ b/packages/slate-react/src/utils/environment.ts @@ -1,3 +1,8 @@ +import React from 'react' + +export const IS_REACT_VERSION_17_OR_ABOVE = + parseInt(React.version.split('.')[0], 10) >= 17 + export const IS_IOS = typeof navigator !== 'undefined' && typeof window !== 'undefined' &&