From 33a36679d9c840c8e9a857b0d3a850c8c275ad06 Mon Sep 17 00:00:00 2001 From: Gabin Aureche Date: Tue, 19 Sep 2017 17:52:38 +0200 Subject: [PATCH] Add a way to customize shouldComponentUpdate logic (#1140) * Add a way to customize shouldComponentUpdate logic * Clean * Warn when returning false in shouldNodeComponentUpdate * Clean --- docs/reference/slate-react/custom-nodes.md | 15 ++++++++++++++ packages/slate-react/src/components/node.js | 22 ++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/docs/reference/slate-react/custom-nodes.md b/docs/reference/slate-react/custom-nodes.md index 24136dd08..ae31ab15c 100644 --- a/docs/reference/slate-react/custom-nodes.md +++ b/docs/reference/slate-react/custom-nodes.md @@ -12,6 +12,7 @@ Slate will render custom nodes for [`Block`](../slate/block.md) and [`Inline`](. - [`parent`](#parent) - [`readOnly`](#readonly) - [`state`](#state) +- [`shouldNodeComponentUpdate`](#shouldnodecomponentupdate) ## Properties @@ -97,3 +98,17 @@ Whether the editor is in "read-only" mode, where all of the rendering is the sam `State` A reference to the current [`State`](../slate/state.md) of the editor. + +## `shouldNodeComponentUpdate` + +By default, Slate implements a `shouldComponentUpdate` preventing useless re-renders for node components. While the default implementation covers most use cases, you can customize the logic to fit your needs. For example: + +```js +class CustomNode extends React.Component { + static shouldNodeComponentUpdate(previousProps, nextProps) { + // return true here to trigger a re-render + } +} +``` + +If `shouldNodeComponentUpdate` returns false, Slate will still figure out whether a re-render is needed or not. diff --git a/packages/slate-react/src/components/node.js b/packages/slate-react/src/components/node.js index a9b94f275..163509ce3 100644 --- a/packages/slate-react/src/components/node.js +++ b/packages/slate-react/src/components/node.js @@ -3,6 +3,7 @@ import Base64 from 'slate-base64-serializer' import Debug from 'debug' import React from 'react' import SlateTypes from 'slate-prop-types' +import logger from 'slate-dev-logger' import Types from 'prop-types' import TRANSFER_TYPES from '../constants/transfer-types' @@ -99,7 +100,26 @@ class Node extends React.Component { // If the `Component` has enabled suppression of update checking, always // return true so that it can deal with update checking itself. - if (Component && Component.suppressShouldComponentUpdate) return true + if (Component && Component.suppressShouldComponentUpdate) { + logger.deprecate('2.2.0', 'The `suppressShouldComponentUpdate` property is deprecated because it led to an important performance loss, use `shouldNodeComponentUpdate` instead.') + return true + } + + // If the `Component` has a custom logic to determine whether the component + // needs to be updated or not, return true if it returns true. + // If it returns false, we still want to benefit from the + // performance gain of the rest of the logic. + if (Component && Component.shouldNodeComponentUpdate) { + const shouldUpdate = Component.shouldNodeComponentUpdate(p, n) + + if (shouldUpdate) { + return true + } + + if (shouldUpdate === false) { + logger.warn('Returning false in `shouldNodeComponentUpdate` does not disable Slate\'s internal `shouldComponentUpdate` logic. If you want to prevent updates, use React\'s `shouldComponentUpdate` instead.') + } + } // If the `readOnly` status has changed, re-render in case there is any // user-land logic that depends on it, like nested editable contents.