mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-10 01:06:37 +02:00
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 https://github.com/facebook/react/pull/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
This commit is contained in:
5
.changeset/five-emus-roll.md
Normal file
5
.changeset/five-emus-roll.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'slate-react': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix useFocused hook in react >= 17
|
@@ -9,6 +9,7 @@ import {
|
|||||||
SlateSelectorContext,
|
SlateSelectorContext,
|
||||||
} from '../hooks/use-slate-selector'
|
} from '../hooks/use-slate-selector'
|
||||||
import { EDITOR_TO_ON_CHANGE } from '../utils/weak-maps'
|
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'
|
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,16 +74,23 @@ export const Slate = (props: {
|
|||||||
|
|
||||||
useIsomorphicLayoutEffect(() => {
|
useIsomorphicLayoutEffect(() => {
|
||||||
const fn = () => setIsFocused(ReactEditor.isFocused(editor))
|
const fn = () => setIsFocused(ReactEditor.isFocused(editor))
|
||||||
document.addEventListener('focus', fn, true)
|
if (IS_REACT_VERSION_17_OR_ABOVE) {
|
||||||
return () => document.removeEventListener('focus', fn, true)
|
// In React >= 17 onFocus and onBlur listen to the focusin and focusout events during the bubbling phase.
|
||||||
}, [])
|
// Therefore in order for <Editable />'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.
|
||||||
useIsomorphicLayoutEffect(() => {
|
document.addEventListener('focusin', fn)
|
||||||
const fn = () => setIsFocused(ReactEditor.isFocused(editor))
|
document.addEventListener('focusout', fn)
|
||||||
document.addEventListener('blur', fn, true)
|
return () => {
|
||||||
return () => {
|
document.removeEventListener('focusin', fn)
|
||||||
document.removeEventListener('focus', fn, true)
|
document.removeEventListener('focusout', fn)
|
||||||
document.removeEventListener('blur', fn, true)
|
}
|
||||||
|
} else {
|
||||||
|
document.addEventListener('focus', fn, true)
|
||||||
|
document.addEventListener('blur', fn, true)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('focus', fn, true)
|
||||||
|
document.removeEventListener('blur', fn, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@@ -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 =
|
export const IS_IOS =
|
||||||
typeof navigator !== 'undefined' &&
|
typeof navigator !== 'undefined' &&
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
|
Reference in New Issue
Block a user