slate: shouldNodeComponentUpdate doesnt catch document.data update

Do you want to request a feature or report a bug?

Potential bug

What’s the current behavior?

I have some global settings in slate object which I keep in document.data. Some nodes depend on those settings and should rerender on change.

I implemented the following function to make it rerender:

shouldNodeComponentUpdate: (previousEditorProps, editorProps) => {
    if (
      previousEditorProps.editor.value.document.data.get('variables') !==
      editorProps.editor.value.document.data.get('variables')
    ) {
      console.log('variable changed, lets rerender');
      return true;
    }

    return undefined;
  },

The problem is that this function will never be called with old and new variables, on change previousEditorProps already contains new variables. Is it intended behaviour or a bug? If this is a bug, I will make some interactive example.

What’s the expected behavior?

previousEditorProps should be called once with old and new variables which would allow me to rerender all custom nodes.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 15 (13 by maintainers)

Most upvoted comments

@ianstormtaylor I didn’t hang onto my shouldNodeComponentUpdate implementation for anything since it never really solved my use case, but here’s an example (among several) of where I’m now using context to update components when relevant data changes (without something that normally triggers a re-render).

Here, BlockContext passes its consumers a beginKey, which is set to the key of the beginning delimiter’s text node for the currently-focused “greater block” (a blockquote, code block, etc.)

My BeginKeyword component switches to the non-Empty font (text becomes visible) whenever the related greater block is focused, then switches back to Empty if focus moves to another area outside the block.

You can see it in action by focusing the QUOTE or SRC block here (hard refresh if you visited before).

import React from 'react';
import { css, cx } from 'react-emotion';

import { BlockContext } from '../../../context';

const style = css`
  font-family: 'Empty';
  line-height: 16px;
`;

const focusedStyle = css`
  font-family: 'Roboto Mono';
`;

const BeginKeyword = ({ isFocused, attributes, children }) => (
  <span {...attributes} className={cx(style, { [focusedStyle]: isFocused })}>
    {children}
  </span>
);

const ContextWrapper = (props) => (
  <BlockContext.Consumer>
    {({ beginKey }) => {
       const { node } = props;
       const isFocused = (node.key === beginKey);
       return <BeginKeyword {...{ isFocused, ...props }} />
     }}
  </BlockContext.Consumer>
);

export default ContextWrapper;

Before, I would have tried using editor.props to pass beginKey into shouldNodeComponentUpdate, then compare to the previous value and see if it had changed. I would re-render all relevant nodes when it changed. In the case of the one above, it would determine if beginKey matched during the render. This never really worked as hoped since the previous editor.props weren’t stored.

Can someone post code of what they were using shouldNodeComponentUpdate for before? and the new way they are handling it with context?