当道具值发生变化时,React不会重新渲染组件

时间:2017-07-25 08:04:54

标签: javascript reactjs

有人可以向我解释为什么在这个例子中,Component2在Component1更新自己的状态后不会改变背景颜色吗?我将背景颜色作为一个值从其他组件的状态传递给组件作为道具,但它不起作用我期待。

当你在有边框上点击一次时,新鲜的渲染框应该在"假请求"之后改变颜色。完成了。



class Component1 extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      color:'red',
      innerText:'Click on me!'
    }
    this.someAsynchronusRequest = this.someAsynchronusRequest.bind(this);
  }
  
  someAsynchronusRequest(){
    setTimeout(() => {
      this.setState({
        color:'blue',
        innerText:'requested completed,it should be blue?'
      })
    },1000)
  
  }
  
  render(){
    return(
    <div onClick={this.renderBox.bind(this)} className="box click">
      <div>{this.state.innerText}</div>
    </div>
    )
  }
  
  renderBox(){
    this.someAsynchronusRequest();
    ReactDOM.render(<Component2 color={this.state.color}/>,document.getElementById('component2'))
  }
}

class Component2 extends React.Component {
  constructor(props){
    super(props)
  }
  
  render(){
    return(
      <div style={{backgroundColor:this.props.color}} className="red box">
      </div>
    )
  }
}

ReactDOM.render(<Component1 />, document.getElementById('component1'))
&#13;
.click {
  text-align:center;
  border:1px solid black;
}

.box {
  width:100px;
  height:100px;
  margin:10px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="component1">
</div>

<div id="component2">
</div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

class Component1 extends React.Component{

  constructor(props){
    super(props)
    
    this.state = {
    
      color:'red',
      innerText:'Click on me!'
    
    }
    
    this.someAsynchronusRequest = this.someAsynchronusRequest.bind(this);
  }
  
  someAsynchronusRequest(){
  
    return new Promise((resolve, reject) => {
      setTimeout(() => {
    
      this.setState({
      
        color:'blue',
        innerText:'requested completed,it should be blue?'
      
      }, () => {
        resolve()
      })
    
    },1000)
    })
  
  }
  
  render(){
  
  
  
    return(
    
    <div onClick={this.renderBox.bind(this)} className="box click">
      <div>{this.state.innerText}</div>
    </div>
    
    )
  
  }
  
  renderBox(){
    
    this.someAsynchronusRequest()
      .then(resolve => {
          ReactDOM.render(<Component2 color={this.state.color}/>,document.getElementById('component2'))
       })
    

  
  
  }

}

class Component2 extends React.Component {

  constructor(props){
  
    super(props)
  
  }
  
  render(){
  
  
    return(
    
      <div style={{backgroundColor:this.props.color}} className="red box">
      
      </div>
    
    )
  
  }

}

ReactDOM.render(<Component1 />, document.getElementById('component1'))
.click {

  text-align:center;
  border:1px solid black;

}

.box {

  width:100px;
  height:100px;
  margin:10px;

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="component1">

</div>

<div id="component2">

</div>

我在someAsynchronusRequest方法中添加了一个promise。请注意,我在setState的回调函数中解决它,因为它是异步的。

问题是你在调用超时函数之前渲染Component2,因此不会使用蓝色渲染新组件(此时尚未更改)。他们渲染Component2(使用ReactDOM)的方式实际上并不是React的惯用方式。相反,你应该像这样在Component1的渲染函数中渲染Component2。这将自动解决异步问题,您可以删除承诺:

render(){
    return(

    <div onClick={this.renderBox.bind(this)} className="box click">
      <div>{this.state.innerText}</div>
      <Component2 color={this.state.color}/>
    </div>

    )

通常,您只想使用ReactDOM.render()来呈现根组件,将其附加到页面上的某个div。其余部分应使用组件的渲染功能进行渲染。