Все свойства ссылки на дочерний компонент, созданной с помощью React.createRef (), не определены в методе componentDidMount

У меня есть компонент React, который отображает другой компонент из сторонней библиотеки, Froala Editor. Я сохраняю ссылку на дочерний компонент с помощью React.createRef ().

В методе componentDidMount я пытаюсь получить доступ к методам в дочерней ссылке. Однако эти методы возвращают значение undefined. Теперь я попытался сделать console.log для самой дочерней ссылки, и я вижу, что эти методы НЕ являются неопределенными.

Дочерний компонент также принимает обратные вызовы, и у меня есть варианты использования, в которых я могу нормально использовать эти методы. Однако, когда я использую ссылку в componentDidMount, все внутренние свойства не определены.

Я новичок в React, поэтому приветствую любую помощь.

import React, { Component } from "react";
import FroalaEditor from "react-froala-wysiwyg";
import styled from "styled-components";

const CustomStyle = styled.div`
  background-color: ${props => (props.isEditOn ? "white" : "unset")};
  padding: ${props => props.padding || "2px"};
  width: ${props =>
    props.width ||
    (props.isPlaceholderVisible ? props.placeholderTextWidth : "unset")};
  white-space: ${props => (props.multiLine ? "wrap" : "nowrap")};
`;

class CustomInlineFroalaEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isPlaceholderVisible: false,
      isEditOn: false
    };
    this.editorRef = React.createRef();
  }

  componentDidMount() {
    if (!this.props.text) {
      this.setState({ isPlaceholderVisible: true });
    }
    console.log(this.getEditorFromReactRef()); //logs the reference just fine. Looking at the log seems like .html in next line should not be undefined
    console.log(this.getEditorFromReactRef().html); //returns undefined..but why?
  }

  handleKeyUp = event => {
    const editor = this.getEditorFromReactRef();
    if (event.key === "Enter" && !this.props.multiLine) {
      this.handleEnter(editor);
    }
  };

  handleEnter = editor => {
    // these commands work just fine so I'm confused as to why the ref in componentDidMount is behaving oddly
    editor.edit.off();
    editor.edit.on();
    this.setState({ isEditOn: false });
    this.handlePlaceholderVisibleOnBlur(editor);
    if (typeof this.props.onEnter === "function") {
      this.props.onEnter();
    }
  };

  handleBlur = () => {
    this.setState({ isEditOn: false });
    this.handlePlaceholderVisibleOnBlur(this.getEditorFromReactRef());
    if (typeof this.props.onBlur === "function") {
      this.props.onBlur();
    }
  };

  //todo: consolidate the setState to one call as it renders everytime
  handleFocus = () => {
    this.setState({ isEditOn: true });
    this.handlePlaceholderVisibleOnFocus(this.getEditorFromReactRef());
    if (typeof this.props.onFocus === "function") {
      this.props.onFocus();
    }
  };

  handlePlaceholderVisibleOnFocus(editor) {
    if (editor.placeholder.isVisible() && this.props.autoSelectOnFocus) {
      editor.html.set(this.props.placeholderText);
      editor.commands.selectAll();
      this.setState({ isPlaceholderVisible: false });
    }
  }

  handlePlaceholderVisibleOnBlur(editor) {
    if (editor.placeholder.isVisible()) {
      this.setState({ isPlaceholderVisible: true });
    }
  }

  getEditorFromReactRef() {
    return this.editorRef.current.editor;
  }

  render() {
    return (
      <CustomStyle
        isPlaceholderVisible={this.state.isPlaceholderVisible}
        placeholderTextWidth={this.props.placeholderTextWidth}
        padding={this.props.padding} //this ensures that the text does not touch the border
        width={this.props.width}
        multiLine={this.props.multiLine}
        isEditOn={this.state.isEditOn}
      >
        <FroalaEditor
          ref={this.editorRef}
          model={this.props.text}
          onModelChange={this.props.handleTextChange}
          config={{
            enter: "", //this disables the auto adding of the <p> tag
            multiLine: this.props.multiLine,
            toolbarInline: true,
            initOnClick: true,
            toolbarButtons: [],
            placeholderText: this.props.placeholderText,
            events: {
              blur: this.handleBlur,
              keyup: this.handleKeyUp,
              click: this.handleFocus
            }
          }}
        />
      </CustomStyle>
    );
  }
}

CustomInlineFroalaEditor.defaultProps = {
  autoSelectOnFocus: true
};

export default CustomInlineFroalaEditor;


person kashive    schedule 16.03.2020    source источник


Ответы (1)


Свойство html из editor может быть неопределенным, если используется опция initOnClick: true,. Методы редактора должны быть доступны, но отложенная инициализация может привести к другому неожиданному поведению [позже].

Вы можете использовать события initialized или initializationDelayed для своих настроек.

person xadm    schedule 17.03.2020
comment
Благодарю за ваш ответ. Я пробовал использовать инициализированное событие. initialized: function() {console.log("initialized with", this.html)} по-прежнему возвращает undefined - person kashive; 17.03.2020
comment
Я бы лучше попробовал 'initialized' : function(e, editor) { console.log('initialized', editor, editor.html); } - this здесь может быть не то, что ты хочешь - person xadm; 17.03.2020
comment
Я попробовал блок кода, но редактор все еще не определен. Я получаю TypeError: Cannot read property 'html' of undefined - person kashive; 23.03.2020
comment
Попробуйте использовать что-то вроде github.com/froala/react -froala-wysiwyg / blob / master / lib / - он уже использует ref fn, все еще действующий метод ... create минимальный воспроизводимый пример - без этого сложно догадаться, что происходит - person xadm; 23.03.2020
comment
Спасибо за указатели @xadm. Прямо сейчас это было отменено, вернемся к этому позже. - person kashive; 22.04.2020