【问题标题】:React child component Re-renders without state change反应子组件在不改变状态的情况下重新渲染
【发布时间】:2017-04-03 10:23:43
【问题描述】:

我将一些数据从一个组件传递到另一个组件(父级到子级)。数据通过输入和按钮单击事件没有任何问题。我通过考虑一些关键事件(是否输入数字)添加了一些验证。当与此验证相关的特定功能被触发时,子组件会自动重新渲染。我不知道为什么。这是我的代码。我使用了通量架构。

主父级(keyevent 发生的地方)

    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;

发生状态变化的子组件

   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;

即使子组件没有更改状态,也会触发渲染功能。我调试了它们正常工作的通量文件。我遇到这个问题的任何原因

【问题讨论】:

    标签: javascript reactjs flux


    【解决方案1】:

    `这里渲染函数被触发,即使状态是
    不被子组件改变

    据我了解,您有一个触发重新渲染 PaserBox 的 setState 函数,并且您不希望它导致重新渲染 PaserBox 的子 ParserTreeBox

    如果是这样,ParserTreeBox重新渲染是很正常的,因为PaserBox的渲染功能包含ParserTreeBox组件。

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

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

    现在它会在决定渲染这个组件之后检查这个方法。

    【讨论】:

    • 你可以看看我面临的问题35.163.71.75。提交表单后,一旦在文本字段中按下某个键,它将重新呈现
    【解决方案2】:

    Component 更改为PureComponent

    class MyComponent extends React.Component {
    
        // ...
    
    
    class MyComponent extends React.PureComponent {
    
        // ...
    

    它实现了shouldComponentUpdate(),同时具有浅的propstate 比较。

    【讨论】:

    • 我尝试了这个,现在子组件需要点击 2 次按钮才能呈现正确的数据。你可以看看我面临的问题35.163.71.75。提交表单后,一旦在文本字段中按下一个键,它将重新呈现。
    猜你喜欢
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 2019-11-19
    • 2021-06-20
    • 1970-01-01
    • 2020-12-30
    • 2017-03-24
    • 2019-04-03
    相关资源
    最近更新 更多