了解如何通过组件跟踪事件

时间:2018-01-23 14:00:07

标签: javascript reactjs

我需要有关如何在Reactjs中解决以下问题的想法:

  • TextEditor - >工具栏 - > PickColorBox

我有组件的关系(父 - >孩子),如上所列。

问题:组件工具栏的状态为showPickColorBox: false,表示组件PickColorBox是否可见。按钮的单击事件触发此状态。我需要的是按钮能够将布尔值切换到正确的状态,即如果组件可见则为true,否则为false。但每次触发按钮事件时,即使PickColorBox组件可见,也会调用工具栏的构造函数并将状态showPickColorBox设置为false

我的解决方案:我需要的是跟踪组件PickColorBox是否可见,以将状态设置为正确的值。阅读一些代码我看到了在根组件中实例化类以跟踪事件的示例。我尝试重现这个例子,但它不起作用,我无法在类中传递作为道具的功能。我甚至不确定是否可以在javascript中实例化一个类,所以我需要一些指南。

任何有关如何解决的帮助,非常感谢任何其他解决方案!

我将代码更改为简化,因此代码中的拼写错误不是问题,除非是关于实例化的类以及如何执行它。另一件事,只是为了澄清代码,我正在使用Draftjs框架,其中组件编辑器,状态EditorState和onChange是继承。

根组件

export default class TextEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
    };
    this.onChange = (editorState) => this.setState({editorState});
    this.modalHandler = new ModalHandler();
  }

  render() {
    const {editorState} = this.state;

    return (
      <div className={'editor-root'} >
        <div className={'editor-toolbar'}>
          <Toolbar
            editorState={editorState}
            onChange={this.onChange}
            modalHandler={this.modalHandler}
          />
        </div>
        <div className={'editor-textarea'} >
          <Editor
            editorState={editorState}
            onChange={this.onChange}
          />
        </div>
      </div>
    );
  }
}

ModalHandler类

export default class ModalHandler {
  let boolShowComponent = false;

  toogleShowComponent = (): boolean => {
    return !boolShowComponent;
  };
}

工具栏组件

export default class Toolbar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showPickColorBox: false
    };
  }

  _onPickColorClick() {
    let bool = this.props.modalHandler.toogleShowComponent()
    this.setState({
      showPickColorBox: bool,
    });
  }

  render() {
    return (
      <div className={'ToolbarEditor'} >
        {this._onPickColorClick.bind(this)}>PickColor</button>
          {
            this.state.showPickColorBox ?
            <PickColorBox
              editorState={this.props.editorState}
              onChange={this.props.onChange}
            /> :
            null
          }
      </div>
    );
  }
}

2 个答案:

答案 0 :(得分:2)

不使用showPickColorBox处理工具栏,而是尝试在TextEditor中定义相同的文件并将其作为道具传递。现在,要更新showPickColorBox,请在TextEditor中定义一个方法并将其作为props传递。

export default class TextEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
      //define here
      showPickColorBox: false

    };
    this.onChange = (editorState) => this.setState({editorState});


    this.modalHandler = new ModalHandler();
  }
  //definehere
  _onPickColorClick(bool) {

    this.setState({
      showPickColorBox: bool,
    });
  }

  render() {
    const {editorState} = this.state;

    return (

      <div className={'editor-root'} >
        <div className={'editor-toolbar'}>
          <Toolbar
            editorState={editorState}
            onChange={this.onChange}
            modalHandler={this.modalHandler}
            //pass here
            _onPickColorClick={this._onPickColorClick}
          />
        </div>
        <div className={'editor-textarea'} >
          <Editor
            editorState={editorState}
            onChange={this.onChange}
          />
        </div>
      </div>
    );
  }
}

现在从工具栏调用:

export default class Toolbar extends React.Component {
  constructor(props) {
    super(props);

  }

  _onPickColorClick() {
    let bool = this.props.modalHandler.toogleShowComponent();
    //use here
    this.props._onPickColorClick(bool);
  }

  render() {
    return (
      <div className={'ToolbarEditor'} >
        {this._onPickColorClick.bind(this)}>PickColor</button>
          {
            this.state.showPickColorBox ?
            <PickColorBox
              editorState={this.props.editorState}
              onChange={this.props.onChange}
            /> :
            null
          }
      </div>
    );
  }
}

答案 1 :(得分:0)

我找到了我正在寻找的解决方案。碰巧我忘了创建一个正确的EventHandler类来跟踪在children组件中触发的事件。所以这是解决方案:

根组件

export default class TextEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(),
    };
    this.onChange = (editorState) => this.setState({editorState});

    /* this name makes more sense instead of modalHandler */
    this.toolbarEventHandler = new ToolbarEventHandler(); 
  }

  render() {
    const {editorState} = this.state;

    return (
      <div className={'editor-root'} >
        <div className={'editor-toolbar'}>
          <Toolbar
            editorState={editorState}
            onChange={this.onChange}
            toolbarEventHandler={this.toolbarEventHandler}
          />
        </div>
        <div className={'editor-textarea'} >
          <Editor
            editorState={editorState}
            onChange={this.onChange}
          />
        </div>
      </div>
    );
  }
}

ToolbarEventHandler (ModalHandler)

/*I will change this class to hold more than one event */
/* Probably change to an array */ 
export default class ToolbarEventHandler {
  constructor() {
    this.boolShowComponent = false;
  }

  get boolShowComponent() {
    return this.boolShowComponent;
  }

  set boolShowComponent(bool){
    this.boolShowComponent = bool;
  }
}

<强>工具栏

export default class Toolbar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showPickColorBox: false
    };
  }

  _onPickColorClick() {
    this.props.toolbarEventHandler.boolShowComponent = !this.props.toolbarEventHandler.boolShowComponent;
    this.setState({
      showComponent: this.props.toolbarEventHandler.boolShowComponent,
    });
  }

  render() {
    return (
      <div className={'ToolbarEditor'} >
        {this._onPickColorClick.bind(this)}>PickColor</button>
          {
            this.state.showPickColorBox ?
            <PickColorBox
              editorState={this.props.editorState}
              onChange={this.props.onChange}
            /> :
            null
          }
      </div>
    );
  }
}