反应流星,反应支柱和内部状态

时间:2017-09-05 14:00:44

标签: javascript mongodb reactjs meteor draftjs

我有一个组件

import React, { Component } from 'react'
import { EditorState, convertToRaw } from 'draft-js'
import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
import draftToHtml from 'draftjs-to-html'

import toolbarOptions from './JpuriTextEditorOptions'

export default class TextEditor extends Component {
  state = {
    editorState: this.props.editorState
  }

  componentWillReceiveProps = nextProps => {
    console.warn('componentWillReceiveProps')
    console.log('nextProps.editorState', nextProps.editorState)
    console.log('this.props.editorState', this.props.editorState)

    this.setState({editorState: nextProps.editorState})
  }

  onEditorStateChange = editorState => this.setState({editorState})

  onBlur = () => this.props.onBlur({key: this.props.myKey, value: draftToHtml(convertToRaw(this.state.editorState.getCurrentContent()))})

  render () {
    return (
      <Editor
        wrapperClassName={this.props.wrapperClassName}
        editorClassName={this.props.editorClassName}
        toolbarClassName={`toolbarAbsoluteTop ${this.props.toolbarClassName}`}

        wrapperStyle={this.props.wrapperStyle}
        editorStyle={this.props.editorStyle}
        toolbarStyle={this.props.toolbarStyle}

        editorState={this.state.editorState}
        onEditorStateChange={this.onEditorStateChange}
        onChange={this.props.onChange}

        toolbarOnFocus
        toolbar={toolbarOptions}

        onFocus={this.props.onFocus}
        onBlur={this.onBlur}
        onTab={this.props.onTab}
      />
    )
  }
}

我传递了一个反应性道具,this.props.editorState 然后我将其设置在内部状态以处理那里的更改。并且只有onBlur我将更改保存到mongo db。

现在有一个问题。 每当我点击编辑器时,我都会看到componentWillReceiveProps记录几次。它发生在每次更改,因此我无法正确使用我的编辑器组件。因为每次点击和更改都会将光标重置为第一个字母。

我正在使用这个draftjs https://github.com/jpuri/react-draft-wysiwyg

修改

该问题的更多细节。 在构造函数或componentDidMount中将状态设置为this.props.editorState正在解决初始状态的问题。 但仍然只剩下一个问题。 在另一个组件中,我有撤消重做功能,可直接与db一起使用。现在,如果我输入一些文字。模糊它我的更改保存到数据库,我可以看到文本,因为内部文本。但是,如果单击撤消按钮,文本将从db中撤消,但由于内部状态,它仍将在编辑器中可见。所以我必须刷新才能看到我的行动撤消。 使用componentWillReceiveProps解决了这个问题,但是由于某些原因,即使不更改props,每次状态更改时都会调用componentWillReceiveProps。从而带来了上述问题。

1 个答案:

答案 0 :(得分:2)

如果您使用此组件的受控模式,则应在内部设置状态,而不是通过道具从外部设置状态。
例如,如果您在收到的每个新道具上设置状态,则没有理由使用内部状态 根据他们的DOCS,你似乎遵循他们的受控EditorState的例子,除非你在每个新道具上覆盖你的州。 我想如果您只是从componentWillReceiveProps中删除此行为 即设置状态:this.setState({editorState: nextProps.editorState})
它应该像预期的那样工作。

这是他们的例子:

import React, { Component } from 'react';
import { EditorState } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';


class ControlledEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
    };
  }

  onEditorStateChange: Function = (editorState) => {
    this.setState({
      editorState,
    });
  };

  render() {
    const { editorState } = this.state;
    return (
      <Editor
        editorState={editorState}
        wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        onEditorStateChange={this.onEditorStateChange}
      />
    )
  }
}

修改
作为评论的后续内容,状态初始化通常在constructor中进行 但是当您想要异步初始化状态时,您不能也不应该在构造函数中执行它(也不能在componentWillMount中),因为在异步操作完成时,render方法将被调用。
最好的地方是componentDidMount或eventHandlers,所以在你的情况下onBlur eventHandler:
     从'react'导入React,{Component};     从'draft-js'导入{EditorState};     从'react-draft-wysiwyg'导入{Editor};

class ControlledEditor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
    };
  }

  onEditorStateChange = (editorState) => {
    this.setState({
      editorState,
    });
  };

  onBlur = (event) => {
    // do async stuff here and update state
  };

  render() {
    const { editorState } = this.state;
    return (
      <Editor
        editorState={editorState}
        wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        onEditorStateChange={this.onEditorStateChange}
        onBlur={this.onBlur}
      />
    )
  }
}