2016-11-18 7 views
3

componentDidMountsetStateを使用してカスタムコンポーネントを更新するのはかなり新しいことですが、これは推奨される方法です。React: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が返すへ[]から)更新されますないことを示しています。下記の実施例(データを取得するためにaxios API呼び出しを含んでいます)。しかし、MyComponentcomponentDidMountによって新たにレンダリングされないという問題があります。 Facebookの反応文書から:

このメソッドの状態を設定すると、再レンダリングがトリガーされます。一度だけ呼び出さMyComponentのコンストラクタ(this.props.data = [])とコンポーネントが再び描画されません。

これはここの場合ではないようです。私はなぜ誰かがこれが何であるか、そして解決策が完了したかどうかを解決する方法か別の方法があるのか​​を説明することができれば素晴らしいだろう。

UPDATE

Iは、(...によって示されるように、マイナスいくつかの無関係な機能)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を入れてレンダリングが2回であることを確認してください。 – Conan

答えて

2

あなたが唯一それがマウント初めて呼び出さMyComponentコンストラクタでは、this antipattern.

の犠牲に下落している、new DataWrapperを通して、あなたの空の配列を渡すと、今、あなたは更新されませんいくつかのローカルな状態を持っていませんあなたの親が何をするかが重要です。

真実のソースを1つだけ持ち、どこにでも1つの状態オブジェクト(特に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> 
) 
} 
関連する問題