2016-05-03 32 views
15

私は、プレゼンテーションコンポーネントをコンテナコンポーネントから分離しようとしています。私はSitesTableSitesTableContainerです。コンテナは、現在のユーザーに基づいて適切なサイトをフェッチするための冗長アクションをトリガーする役割を果たします。問題は、コンテナコンポーネントが最初にレンダリングされた後に、現在のユーザーが非同期にフェッチされることです。つまり、コンテナコンポーネントは、SitesTableに送信するデータを更新するcomponentDidMount関数でコードを再実行する必要があることを認識しません。私は、その小道具(ユーザ)の1つが変更されたときにコンテナコンポーネントを再レンダリングする必要があると思う。どのように私はこれを正しく行うのですか?小道具変更時に反応コンポーネントを再レンダリングする

class SitesTableContainer extends React.Component { 
    static get propTypes() { 
     return { 
     sites: React.PropTypes.object, 
     user: React.PropTypes.object, 
     isManager: React.PropTypes.boolean 
     } 
    } 

    componentDidMount() { 
     if (this.props.isManager) { 
     this.props.dispatch(actions.fetchAllSites()) 
     } else { 
     const currentUserId = this.props.user.get('id') 
     this.props.dispatch(actions.fetchUsersSites(currentUserId)) 
     } 
    } 

    render() { 
     return <SitesTable sites={this.props.sites}/> 
    } 
} 

function mapStateToProps(state) { 
    const user = userUtils.getCurrentUser(state) 

    return { 
    sites: state.get('sites'), 
    user, 
    isManager: userUtils.isManager(user) 
    } 
} 

export default connect(mapStateToProps)(SitesTableContainer); 
+0

のようになります方法です変更する – thsorens

+0

なぜあなたは、その小道具を変更していない場合、SitesTableを再レンダリングする必要がありますか? – QoP

+0

@QoP 'componentDidMount'でディスパッチされているアクションは、アプリケーション状態の' sites'ノードを変更し、 'SitesTable'に渡されます。 SitesStableの 'sites'ノードが変更されます。 – David

答えて

25

componentWillReceivePropsメソッドで条件を追加する必要があります。

これはあなたがたときに小道具何かを起動したい場合は、componentDidUpdateのような利用できるいくつかの他の機能を持っている、または、おそらく1があなたの、componentWillReceiveProps(nextProps)を探して、あなたのコンポーネントが

constructor(){ 
    this.updateUser = this.updateUser.bind(this); 
} 


componentDidMount() { 
    this.updateUser(); 

} 

componentWillReceiveProps(nextProps) { 
    if(JSON.stringify(this.props.user) !== JSON.stringify(nextProps.user)) // Check if it's a new user, you can also use some unique, like the ID 
    { 
      this.updateUser(); 
    } 
} 

updateUser() { 
    if (this.props.isManager) { 
    this.props.dispatch(actions.fetchAllSites()) 
    } else { 
    const currentUserId = this.props.user.get('id') 
    this.props.dispatch(actions.fetchUsersSites(currentUserId)) 
    } 
} 
+0

JSON.stringifyは、安定している(仕様ではない)場合にのみ、このような比較に使用できるので、同じ入力に対して同じ出力を生成します。 不要なリロードを避けるために、ユーザーオブジェクトのidプロパティを比較するか、propsのuserId-sを渡して比較することをお勧めします。 –

5
componentWillReceiveProps(nextProps) { // your code here} 

私はそれはあなたが必要なイベントだと思います。 componentWillReceivePropsは、コンポーネントが小道具で何かを受け取るたびに起動します。そこからあなたの点検をして、あなたがしたいことを何でもしてください。

2

私はこのanswerをご覧になり、自分が行っていることに関連しているかどうかを確認することをおすすめします。あなたの本当の問題を理解していれば、非同期アクションを正しく使用せず、reduxの "store"を更新するだけです。これによりコンポーネントが新しい小道具で自動的に更新されます。

あなたのコードのこのセクション:

componentDidMount() { 
     if (this.props.isManager) { 
     this.props.dispatch(actions.fetchAllSites()) 
     } else { 
     const currentUserId = this.props.user.get('id') 
     this.props.dispatch(actions.fetchUsersSites(currentUserId)) 
     } 
    } 

はコンポーネントでトリガされていないなら、それはあなたの最初の要求を実行した後に処理する必要があります。

redux-thunkから、この例を見てください:

function makeASandwichWithSecretSauce(forPerson) { 

    // Invert control! 
    // Return a function that accepts `dispatch` so we can dispatch later. 
    // Thunk middleware knows how to turn thunk async actions into actions. 

    return function (dispatch) { 
    return fetchSecretSauce().then(
     sauce => dispatch(makeASandwich(forPerson, sauce)), 
     error => dispatch(apologize('The Sandwich Shop', forPerson, error)) 
    ); 
    }; 
} 

あなたは必ずしもReduxの-サンクを使用する必要はありませんが、それはこのようなシナリオについてのあなたの理由を助けると一致するコードを記述します。

+0

そうですね。しかし、あなたのコンポーネントに 'makeASandwichWithSecretSauce'をどこに送りますか? – David

+0

関連する例を使ってレポにリンクします。あなたのアプリに反応ルータを使用していますか? – TameBadger

+0

はい私は反応ルータを使用します – David

関連する問題