2016-11-18 753 views
3

我是相當新的反應和努力更新自定義組件使用componentDidMountsetState,這似乎是推薦的方式。下面的例子(包括axios API調用來獲取數據):反應:componentDidMount + setState不重新渲染組件

import React from 'react'; 
import {MyComponent} from 'my_component'; 
import axios from 'axios'; 


export default class Example extends React.Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      data: [] 
     }; 
    } 

    GetData() { 
     return axios.get('http://localhost:5000/<route>'); 
    } 

    componentDidMount() { 
     this.GetData().then(
       (resp) => { 
        this.setState(
         {data: resp.data} 
        ) 
       } 
      ) 
    } 

    render() { 
     return (
      <MyComponent data={this.state.data} /> 
     ); 
    } 
} 

略低於render()console.log(this.state.data)表明this.state.data確實得到更新(從[]到任何API返回)。但是,問題似乎是MyComponent不會被componentDidMount重新生成。從Facebook的反應文檔:

在這個方法中設置狀態會觸發重新呈現。

這似乎並不在這裏的情況:中MyComponent構造函數只被調用一次(其中this.props.data = [])和成分不會再次呈現。如果有人能夠解釋這是爲什麼,以及是否有解決方案或完全不同的方式來完成更新,我會很棒。

UPDATE

我已經添加了MyComponent代碼(減去一些無關緊要的功能,通過...所示)。 console.log(data_array)打印一個空數組。

import React from 'react'; 

class DataWrapper { 
    constructor(data) { 
    this._data = data; 
    } 

    getSize() { 
    return this._data.length; 
    } 

    ... 
} 


export class MyComponent extends React.Component { 
     constructor(props) { 
     super(props); 

     this._dataWrapper = new DataWrapper(this.props.data); 

     this.state = { 
      data_array: this._dataWrapper, 
     }; 

     } 

    render() { 
     var {data_array} = this.state; 
     console.log(data_array); 
     return (
       ... 
     ); 
    } 
} 
+0

你可以顯示'MyComponent'的代碼嗎?你在容器組件中做的看起來是正確的,但是在子組件內可能會發生一些奇怪的事情。 –

+3

構造函數不必多次調用。 React已經創建了這個對象,它不需要再次這樣做。如果你在'componentWillReceiveProps'中記錄一些東西,你會看到工作正常。如果MyComponent在'this.props.data'中呈現出某些內容,那麼它將被更新。 –

+0

是的,爲什麼需要再次調用構造函數?嘗試在渲染中放置一個console.log以確認它渲染兩次。 – Conan

回答

2

你是this antipattern.

的犧牲品在MyComponent構造函數,它只有被稱爲第一次安裝,通過你的空數組通過new DataWrapper現在你將永遠不會更新一些地方的國家沒有重要的是你的父母做什麼。

擁有一個真相源,任何地方只有一個狀態對象(特別是對於像Ajax響應),並通過道具傳遞這些對象總是更好。事實上,你甚至可以把MyComponent寫成一個簡單的函數,而不是一個類。

class Example extends Component { 
    state = { data: [] } 

    GetData() { .. } 

    componentDidMount() { 
    this.GetData().then(res => 
     this.setState({data: new DataWrapper(res.data)}) 
    ) 
    } 

    render() { return <MyComponent data={this.state.data} /> } 
} 

... 

function MyComponent (props) { 
    // props.data will update when your parent calls setState 
    // you can also call DataWrapper here if you need MyComponent specific wrapper 
    return (
    <div>..</div> 
) 
}