diff --git a/packages/slate-react/src/components/editable.tsx b/packages/slate-react/src/components/editable.tsx index 1ef3ebf55..b78a6f87c 100644 --- a/packages/slate-react/src/components/editable.tsx +++ b/packages/slate-react/src/components/editable.tsx @@ -1,10 +1,4 @@ -import React, { - useLayoutEffect, - useEffect, - useRef, - useMemo, - useCallback, -} from 'react' +import React, { useEffect, useRef, useMemo, useCallback } from 'react' import { Editor, Element, NodeEntry, Node, Range, Text } from 'slate' import debounce from 'debounce' import scrollIntoView from 'scroll-into-view-if-needed' @@ -15,6 +9,7 @@ import { IS_FIREFOX, IS_SAFARI } from '../utils/environment' import { ReactEditor } from '..' import { ReadOnlyContext } from '../hooks/use-read-only' import { useSlate } from '../hooks/use-slate' +import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect' import { DOMElement, DOMNode, @@ -106,7 +101,7 @@ export const Editable = ( ) // Update element-related weak maps with the DOM element ref. - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (ref.current) { EDITOR_TO_ELEMENT.set(editor, ref.current) NODE_TO_ELEMENT.set(editor, ref.current) @@ -121,7 +116,7 @@ export const Editable = ( // leaky polyfill that only fires on keypresses or clicks. Instead, we want to // fire for any change to the selection inside the editor. (2019/11/04) // https://github.com/facebook/react/issues/5785 - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { window.document.addEventListener('selectionchange', onDOMSelectionChange) return () => { @@ -136,7 +131,7 @@ export const Editable = ( // built-in `onBeforeInput` is actually a leaky polyfill that doesn't expose // real `beforeinput` events sadly... (2019/11/04) // https://github.com/facebook/react/issues/11211 - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (ref.current) { // @ts-ignore The `beforeinput` event isn't recognized. ref.current.addEventListener('beforeinput', onDOMBeforeInput) @@ -151,7 +146,7 @@ export const Editable = ( }, []) // Whenever the editor updates, make sure the DOM selection state is in sync. - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { const { selection } = editor const domSelection = window.getSelection() diff --git a/packages/slate-react/src/components/element.tsx b/packages/slate-react/src/components/element.tsx index c6793716f..37d36d021 100644 --- a/packages/slate-react/src/components/element.tsx +++ b/packages/slate-react/src/components/element.tsx @@ -1,4 +1,4 @@ -import React, { useLayoutEffect, useRef } from 'react' +import React, { useRef } from 'react' import getDirection from 'direction' import { Editor, Node, Range, NodeEntry, Element as SlateElement } from 'slate' @@ -6,6 +6,7 @@ import Text from './text' import Children from './children' import { ReactEditor, useEditor, useReadOnly } from '..' import { SelectedContext } from '../hooks/use-selected' +import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect' import { NODE_TO_ELEMENT, ELEMENT_TO_NODE, @@ -111,7 +112,7 @@ const Element = (props: { } // Update element-related weak maps with the DOM element ref. - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (ref.current) { KEY_TO_ELEMENT.set(key, ref.current) NODE_TO_ELEMENT.set(element, ref.current) diff --git a/packages/slate-react/src/components/text.tsx b/packages/slate-react/src/components/text.tsx index ec4597fab..6f7c5b139 100644 --- a/packages/slate-react/src/components/text.tsx +++ b/packages/slate-react/src/components/text.tsx @@ -1,9 +1,10 @@ -import React, { useLayoutEffect, useRef } from 'react' +import React, { useRef } from 'react' import { Range, Element, Text as SlateText } from 'slate' import Leaf from './leaf' import { ReactEditor, useEditor } from '..' import { RenderLeafProps } from './editable' +import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect' import { KEY_TO_ELEMENT, NODE_TO_ELEMENT, @@ -44,7 +45,7 @@ const Text = (props: { } // Update element-related weak maps with the DOM element ref. - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (ref.current) { KEY_TO_ELEMENT.set(key, ref.current) NODE_TO_ELEMENT.set(text, ref.current) diff --git a/packages/slate-react/src/hooks/use-isomorphic-layout-effect.ts b/packages/slate-react/src/hooks/use-isomorphic-layout-effect.ts new file mode 100644 index 000000000..2587f0b65 --- /dev/null +++ b/packages/slate-react/src/hooks/use-isomorphic-layout-effect.ts @@ -0,0 +1,7 @@ +import { useLayoutEffect, useEffect } from 'react' + +/** + * Prevent warning on SSR by falling back to useEffect when window is not defined + */ +export const useIsomorphicLayoutEffect = + typeof window !== 'undefined' ? useLayoutEffect : useEffect