Slate: Wrap all nodes and marks in default shouldComponentUpdate

Created on 21 Jul 2016  Â·  8Comments  Â·  Source: ianstormtaylor/slate

Right now it's only being applied to the default renderers, but there's a good chance that people don't implement them for custom renderers (the examples are a good example of omitting this) and it slows things down a lot. Instead, it might be nice to have them wrapped by default with a component with the proper shouldComponentUpdate, but then to allow for defining your own with a static property on the component like suppressShouldComponentUpdate or similar.

âš‘ perf

All 8 comments

I currently do this with the following util.

pure.js

import React, { Component } from 'react';
import shallowEqual from 'fbjs/lib/shallowEqual';

/**
 * Creates a pure component by wrapping the given Component so that the
 * component only renders initially and when it receives new prop instances.
 * A shallow equivalence on the wrapped component's props is done.
 */
function pure(WrappedComponent) {
  class PureComponent extends Component {
    shouldComponentUpdate(nextProps) {
      return !shallowEqual(this.props, nextProps);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return PureComponent;
}

export default pure;

Then in my editor implementation:

const NODES = {
  'block-quote': pure(props => <blockquote {...props.attributes}>{props.children}</blockquote>),
  'bulleted-list': pure(props => <ul {...props.attributes}>{props.children}</ul>),
  ...
};

Note: you could expand the above to include a helpful displayName on the wrapped component. I do this with another set of helpers. It's useful for debugging in chrome.

@ctrlplusb no need for shallowEqual, slate is using Immutables.

A simple !== on immutable props would suffice

@arekkas yep, it is doing that. it's shallow comparing the props object which does a !== on each prop.

/**
 * Performs equality by iterating through keys on an object and returning false
 * when any key has values which are not strictly equal between the arguments.
 * Returns true when the values of all keys are strictly equal.
 */
function shallowEqual(objA, objB) {
  if (is(objA, objB)) {
    return true;
  }

  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
    return false;
  }

  var keysA = Object.keys(objA);
  var keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  for (var i = 0; i < keysA.length; i++) {
    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
      return false;
    }
  }

  return true;
}

Ah right, thanks!

Done now by default for nodes!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

varoot picture varoot  Â·  3Comments

ianstormtaylor picture ianstormtaylor  Â·  3Comments

bunterWolf picture bunterWolf  Â·  3Comments

ianstormtaylor picture ianstormtaylor  Â·  3Comments

markolofsen picture markolofsen  Â·  3Comments