2017-05-31 72 views
2

我在這裏碰到了一堵磚牆,這意味着我無法完全弄清楚爲什麼接下來的兩個版本的代碼行爲如此不同。React動態渲染組件(對象分配與函數返回)

在第一個版本,當我初始化一個this.childComponent = (<ChildComp />),其道具似乎並不當我改變了Parent的狀態(通過setState())來更新。即使實際調用了setState(),並且Parent的狀態已更新,也會發生這種情況。

在第二個版本中,當我實際初始化一個返回組件的函數(this.childComponent =() => {return (<ChildComp />)})時,一切都像魅力一樣工作,道具被更新。 我正在使用第二個版本(因爲它的工作原理),但我想了解爲什麼這個工程和第一個不工作。

這裏的子組件:

class Child extends React.Component { 
    render() { 
    return (
     <button onClick=(this.props.setValue())> 
     {this.props.value} 
     </button> 
    ) 
    } 
} 

我父組件的下兩個版本:

class Parent extends React.Component { 
    constructor() { 
    this.state = { 
     value: 1 
    } 
    this.childComponent = (
     <Child value={this.state.value} 
     setValue={() => this.setValue()}/> 
    ) 
    } 
    setValue() { 
    this.setState({value: 2}) 
    } 
    render() { 
    return ({this.childComponent}) 
    } 
} 

2.(該this.childComponent是現在是一個返回反應元素的函數)

class Parent extends React.Component { 
    constructor() { 
    this.state = { 
     value: 1 
    } 
    this.childComponent =() => { 
     return (
     <Child value={this.state.value} 
     setValue={() => this.setValue()}/> 
    ) 
    } 
    } 
    setValue() { 
    this.setState({value: 2}) 
    } 
    render() { 
    return ({this.childComponent()}) 
    } 
} 

我試圖簡化代碼,所以我的問題更容易理解。

預先感謝您

+1

在您的第一個(損壞的)版本中,子組件是靜態定義的並且再也不會更改。 – pscl

+1

您在第一種情況下沒有返回'render(){ return {this.childComponent} }'否則可以使用子組件是靜態的 –

+0

明白了,感謝您的解釋 –

回答

1

作出反應的工作片段使用了一個名爲reconciliation每有一個在其內部狀態發生變化時,能夠有效地更新DOM戰略。通常,這發生在setState呼叫之後。

在第一個示例中,Parent組件中的render方法總是返回相同的Child組件,因爲它在constructor中僅創建一次。因此,對帳算法沒有發現任何更改,因爲沒有任何更改。

我想指出<Child value={this.state.value} setValue={() => this.setValue()}/>只是React.createElement(Child, {value: this.state.value, setValue:() => this.setValue()}, null)的語法糖。 createElement只是返回一個對象。

在第二個示例中,每調用render,您都會調用childComponent,然後創建一個新的Child組件。

1

你不必因爲

this.childComponent = (
    <Child value={this.state.value} 
    setValue={() => this.setValue()}/> 
) 

在現在只執行一次,是一個靜態值的構造定義在第一種情況下回報。

而它會工作,因爲它是一個函數,每次被調用時都會執行。

如果您想按照第一種方法進行操作,請在render中定義childcomponent而不是構造函數,因爲每次更改都會調用render。你的代碼也有很多錯誤。見下面

class Parent extends React.Component { 
 
    constructor() { 
 
    super(); 
 
    this.state = { 
 
     value: 1 
 
    } 
 
    
 
    } 
 
    setValue() { 
 
    this.setState({value: 2}) 
 
    } 
 
    render() { 
 
     const childComponent = (
 
     <Child value={this.state.value} 
 
     setValue={() => this.setValue()}/> 
 
    ) 
 
    return (<div>{childComponent}</div>) 
 
    } 
 
} 
 

 
class Child extends React.Component { 
 
    render() { 
 
    return (
 
     <button onClick={this.props.setValue}> 
 
     {this.props.value} 
 
     </button> 
 
    ) 
 
    } 
 
} 
 

 
ReactDOM.render(<Parent/>, document.getElementById('app'))
<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="app"></div>

+0

增加了解釋和工作第一種方法的片段 –