React child 组件 Re-renders 没有状态变化

React child component Re-renders without state change

我正在将一些数据从一个组件传递到另一个组件(parent 到 child)。输入和按钮单击事件的数据传递没有任何问题。我通过考虑一些关键事件(是否输入数字)添加了一些验证。当与此验证相关的特定功能被触发时,child 组件会自动 re-renders。我不知道为什么。这是我的代码。我用过助焊剂架构。

主要Parent(关键事件发生的地方)

    const validatebox = (textStatus) => {

    if (textStatus.length > 100) {
      return {
              error: '*status is too long',
            };
    }  else if (textStatus === '') {
      return {
              error: '*status cannot be empty',
            };
    }  else {
      return true;
    }
}


class PaserBox extends React.Component{

      constructor(props) {
            super(props);
            this.state = {
              textStatus: '',
              tags:{},
              showResults: false
            };

      }

      parse = () => {

        let status = this.refs.textinput.getValue();

        if(validatebox(status).error) {
          this.setState({
            textStatus: validatebox(status).error
          });
          return;

        }
        else {

          Actions.SendDataToTag(status);
          this.setState({ showResults: true });
          console.log(status);


        }
          this.clearText();
      };

      clearText = () => {
        document.getElementById('language').value = '';
      };

      handleKey = (e) =>{
        if (e.key === 'Enter') {
            this.parse();
        } 
        else {
          var keycode = e.which;
          if ((e.shiftKey == false && (keycode == 46 || keycode == 8 || keycode == 37 || keycode == 39 || (keycode >= 48 && keycode <= 57)))) {
            this.setState({
                textStatus: 'cannot enter numbers'
            });
          }
          else {
            this.setState({
              textStatus: ''
            });
          }
        }
      };

      handleKeyDown = (e) => {
        if (e.keyCode == 8) {
          this.setState({
              textStatus: ''
          });
        }
      };

      render(){
        return(
          <div>
            <Paper className="row col-xs-12 col-sm-12 col-md-12" style={style} zDepth={1}>
              <div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <TextField
                  fullWidth={true}
                  style={textfieldstyle}
                  errorText={this.state.textStatus}
                  ref="textinput"
                  onKeyPress={this.handleKey}
                  onKeyDown={this.handleKeyDown}
                  hintText="Enter sentence ..."
                  className="col-xs-12 col-sm-12 col-md-12"
                  name="ta"
                  id="language"/>
              </div>
            <div className="col-xs-9 col-sm-9 col-md-9"/>
            <div className="col-xs-3 col-sm-3 col-md-3" style={style_button}>
              <RaisedButton  secondary={true} label="Parse" onTouchTap={this.parse}/>
            </div>
            <div className="col-xs-1 col-sm-1 col-md-1"/>
            </Paper>
            <label style={styles}>Please enter sentences with correct grammar</label>
            <br/>
            { this.state.showResults ?  <div className="row">
                                          <div className="col-md-10">
                                            <ParserTreeBox/>
                                          </div>
                                          <div className="col-md-2">
                                            <ParserTags/>
                                          </div>
                                        </div> : null }
          </div>
        );
      }

}

export default PaserBox;

状态发生变化的 child 组件

   class ParserTreeBox extends React.Component{

  constructor(props) {
    super(props);
      this.state = {
        data: [],
        taggedData:{}
      }

     this._onChange = this._onChange.bind (this);
  }

  componentWillMount(){
    Store.addChangeListener(this._onChange);
  }

  componentWillUnmount(){
    Store.removeChangeListener(this._onChange);
  }

  _onChange(){
     this.setState({taggedData:Store.getData()});
  }

   render(){
     return(
        <div>
          <div>
            <ParserTree data={this.state.taggedData} />
          </div>
        </div>
     );
   }

}

export default ParserTreeBox;

这里渲染函数被触发,即使状态没有被child components.I 调试的通量文件改变它们正常工作。我遇到这个问题的任何原因

`Here the render function get triggered even though the states are
not changed by the child components

据我了解,您有一个 setState 函数可以触发重新渲染 PaserBox,但您不希望它导致重新渲染作为 PaserBox 子级的 ParserTreeBox

如果是的话ParserTreeBox重新渲染是很正常的,因为PaserBox的渲染函数包含了ParserTreeBox组件

当它在PaserBox的渲染函数中时,它只是传递数据。但是你仍然可以忽略 ParserTreeBox 组件在 ParserTreeBox 端重新渲染 shouldComponentUpdate(nextProps, nextState) 函数。

shouldComponentUpdate(nextProps, nextState){
 return this.state.taggedData == nextState.taggedData ? false : true
}

现在它将在决定此组件的渲染后检查此方法。

Component更改为PureComponent:

class MyComponent extends React.Component {

    // ...


class MyComponent extends React.PureComponent {

    // ...

它通过浅层 propstate 比较实现 shouldComponentUpdate()