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

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

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

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

Я новичок ie с 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;

1 Ответ

0 голосов
/ 17 марта 2020

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

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

...