1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-18 13:11:17 +02:00

implement isomorphic layout effect (#3262)

supresses warning on SSR when using useLayoutEffect by falling back
to useEffect when window is undefined

neither useLayoutEffect nor useEffect is run on server
This commit is contained in:
Eddy Wilson
2019-12-06 13:37:50 -06:00
committed by Ian Storm Taylor
parent 1389093f06
commit 56d798a943
4 changed files with 19 additions and 15 deletions

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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