Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior of onBlur/onFocus callbacks for FunctionComponent with Hooks #2798

Closed
CCinCapital opened this issue May 17, 2019 · 3 comments

Comments

@CCinCapital
Copy link

CCinCapital commented May 17, 2019

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

A bug

What's the current behavior?

please refer to the code attached in later section

onBlur that attached to Editor does not respect the wrapper component's editorValue created using useState hook.

What's the expected behavior?

When onBlur is called, it should pick up the correct editorValue

Screen Shot

Code

import React, { FunctionComponent, useState } from 'react';
import { Value } from 'slate';
import { Editor } from 'slate-react';

export interface IProps {
  // scroll down to `initialValue` section for the value
  initialValue: string;
}

const RichTextEditor: FunctionComponent<IProps> = (props) => {
  const { initialValue: initialValueString } = props;
  const editorValueObject = Value.fromJSON(JSON.parse(initialValueString) || {});

  const [editorValue, setEditorValue] = useState(editorValueObject);

  const log = (desc: string, color: string) => {
    const currentValueString = JSON.stringify(editorValue.toJSON());
    console.log(
      `%c${desc} ${currentValueString === initialValueString}`,
      `background:${color}; color: white; padding: 8px;`
    );
  };

  const handleChange = (editor: Editor) => setEditorValue(editor.value);

  log('Render: is currentValue === initialValue ? ', 'green');

  // expect to log `false`
  const handleBlur = () => {
    log('onBlur: is currentValue === initialValue ? ', 'red');
  };

  return (
    <div>
      <Editor onChange={handleChange} onBlur={handleBlur} value={editorValue} />
    </div>
  );
};

export default RichTextEditor;

Info

  • Browser
    Google Chrome
    Google Chrome is up to date
    Version 74.0.3729.157 (Official Build) (64-bit)
  • Packages
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "slate": "^0.44.10",
    "slate-plain-serializer": "^0.6.34",
    "slate-react": "^0.21.16",
initialValue
{
  "object": "value",
  "document": {
    "object": "document",
    "data": {},
    "nodes": [
      {
        "object": "block",
        "type": "heading-one",
        "data": {},
        "nodes": [
          {
            "object": "text",
            "leaves": [
              {
                "object": "leaf",
                "text": "Objective",
                "marks": []
              }
            ]
          }
        ]
      },
      {
        "object": "block",
        "type": "paragraph",
        "data": {},
        "nodes": [
          {
            "object": "text",
            "leaves": [
              {
                "object": "leaf",
                "text": "Since it's rich text, you can do things like turn a selection of text ",
                "marks": []
              },
              {
                "object": "leaf",
                "text": "bold",
                "marks": [
                  {
                    "object": "mark",
                    "type": "bold",
                    "data": {}
                  }
                ]
              },
              {
                "object": "leaf",
                "text": ", or add a semantically rendered block quote in the middle of the page, like this:",
                "marks": []
              }
            ]
          }
        ]
      },
      {
        "object": "block",
        "type": "block-quote",
        "data": {},
        "nodes": [
          {
            "object": "text",
            "leaves": [
              {
                "object": "leaf",
                "text": "A wise quote.",
                "marks": []
              }
            ]
          }
        ]
      },
      {
        "object": "block",
        "type": "paragraph",
        "data": {},
        "nodes": [
          {
            "object": "text",
            "leaves": [
              {
                "object": "leaf",
                "text": "Try it out for yourself!",
                "marks": []
              }
            ]
          }
        ]
      }
    ]
  }
}
@CCinCapital
Copy link
Author

CCinCapital commented Jun 24, 2019

Closing this because this seems to be an issue from React itself.
I'm having the exact same issue with other libraries.

similar issue: lovasoa/react-contenteditable#161


[edit]: attached a similar issue

@flakekun
Copy link

flakekun commented Jul 24, 2019

I had the same issue and was resorted to using ref object pointed to editor state.

  ...
  const editorStateRef = React.useRef(editorState);
  React.useEffect(() => {
    editorStateRef.current = editorState;
  }, [editorState]);
  ...

Demo of the incorrect behavior:
https://codesandbox.io/s/slate-do-not-react-to-onblur-onkeydown-changes-egb37

Demo of fix using ref object:
https://codesandbox.io/s/fixed-slate-do-not-react-to-onblur-onkeydown-changes-57wkq

@ianstormtaylor
Copy link
Owner

I believe that this may be fixed by #3093, which has changed a lot of the logic in Slate and slate-react especially. I'm going to close this out, but as always, feel free to open a new issue if it persists for you. Thanks for understanding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants