Skip to content

Commit f6b7ca1

Browse files
authored
Run <Slate />'s focus event listeners after <Editable />'s focus handlers in React >= 17 (#4920)
* use focusin and focusout without capture if react >= 17 See facebook/react#19186 for details on changes to `onFocus` and `onBlur` * more accurate name for react version check const * add changeset * add comment about react >= 17 focus event listeners
1 parent 9892cf0 commit f6b7ca1

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

.changeset/five-emus-roll.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'slate-react': patch
3+
---
4+
5+
fix useFocused hook in react >= 17

packages/slate-react/src/components/slate.tsx

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
SlateSelectorContext,
1010
} from '../hooks/use-slate-selector'
1111
import { EDITOR_TO_ON_CHANGE } from '../utils/weak-maps'
12+
import { IS_REACT_VERSION_17_OR_ABOVE } from '../utils/environment'
1213
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
1314

1415
/**
@@ -73,16 +74,23 @@ export const Slate = (props: {
7374

7475
useIsomorphicLayoutEffect(() => {
7576
const fn = () => setIsFocused(ReactEditor.isFocused(editor))
76-
document.addEventListener('focus', fn, true)
77-
return () => document.removeEventListener('focus', fn, true)
78-
}, [])
79-
80-
useIsomorphicLayoutEffect(() => {
81-
const fn = () => setIsFocused(ReactEditor.isFocused(editor))
82-
document.addEventListener('blur', fn, true)
83-
return () => {
84-
document.removeEventListener('focus', fn, true)
85-
document.removeEventListener('blur', fn, true)
77+
if (IS_REACT_VERSION_17_OR_ABOVE) {
78+
// In React >= 17 onFocus and onBlur listen to the focusin and focusout events during the bubbling phase.
79+
// Therefore in order for <Editable />'s handlers to run first, which is necessary for ReactEditor.isFocused(editor)
80+
// to return the correct value, we have to listen to the focusin and focusout events without useCapture here.
81+
document.addEventListener('focusin', fn)
82+
document.addEventListener('focusout', fn)
83+
return () => {
84+
document.removeEventListener('focusin', fn)
85+
document.removeEventListener('focusout', fn)
86+
}
87+
} else {
88+
document.addEventListener('focus', fn, true)
89+
document.addEventListener('blur', fn, true)
90+
return () => {
91+
document.removeEventListener('focus', fn, true)
92+
document.removeEventListener('blur', fn, true)
93+
}
8694
}
8795
}, [])
8896

packages/slate-react/src/utils/environment.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import React from 'react'
2+
3+
export const IS_REACT_VERSION_17_OR_ABOVE =
4+
parseInt(React.version.split('.')[0], 10) >= 17
5+
16
export const IS_IOS =
27
typeof navigator !== 'undefined' &&
38
typeof window !== 'undefined' &&

0 commit comments

Comments
 (0)