2017-07-25 67 views
0

有人可以向我解釋爲什麼在這個例子中Component2不會在Component1更新自己的狀態後改變背景顏色嗎?我將背景顏色作爲一個值從其他組件的狀態傳遞給組件作爲道具,但它不工作,因爲我的預期。React doesnt rerender component when props value is being change

當你點擊邊界框時,新的渲染框應該在「假請求」完成後改變顏色。

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'))
.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>

+1

如果你不使用'ReactDOM.render'就會容易得多。你有這樣做的原因嗎? –

+0

我這樣做來渲染模態,我如何做到這一點,如果我有很多不同的模態窗口? –

+0

根據您在狀態中切換的某些道具渲染它們。您可以在組件上使用'renderSomeModal'函數,該函數根據組件狀態返回null或模態JSX。你也不應該在構造函數或'render'方法中使用'setState'。最好的地方是在'componentDidMount'中。 –

回答

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方法內的承諾。請注意,我在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()來渲染根組件,其連接到頁面上的一些格。其餘部分應該使用組件的渲染功能進行渲染。

+0

感謝您的回答,直到現在我還沒有想過,我在特定的容器中渲染了不同的模態,並通過ReactDOM手動渲染它們。我將嘗試實現您的想法,謝謝 –