1. ホーム
  2. reactjs

[解決済み] プロップ変更時にReactコンポーネントを再レンダリングする

2022-08-02 06:12:23

質問

コンテナコンポーネントから表示用コンポーネントを分離しようとしています。私は SitesTableSitesTableContainer . コンテナは、現在のユーザーに基づいて適切なサイトを取得するためにreduxアクションをトリガーする役割を担っています。

問題は、コンテナコンポーネントが最初にレンダリングされた後に、現在のユーザが非同期にフェッチされることです。つまり、コンテナ コンポーネントは、その componentDidMount 関数に送信するデータを更新するコードを再実行する必要があることを、コンテナ コンポーネントは知らないということです。 SitesTable . 私は、コンテナコンポーネントのプロップの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);

どのように解決するのですか?

の中に条件を追加する必要があります。 componentDidUpdate メソッドに条件を追加する必要があります。

この例では fast-deep-equal を使用してオブジェクトを比較しています。

import equal from 'fast-deep-equal'

...

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

componentDidMount() {
  this.updateUser();
}

componentDidUpdate(prevProps) {
  if(!equal(this.props.user, prevProps.user)) // Check if it's a new user, you can also use some unique property, like the ID  (this.props.user.id !== prevProps.user.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))
  }  
}

フックの使用 (React 16.8.0+)

import React, { useEffect } from 'react';

const SitesTableContainer = ({
  user,
  isManager,
  dispatch,
  sites,
}) => {
  useEffect(() => {
    if(isManager) {
      dispatch(actions.fetchAllSites())
    } else {
      const currentUserId = user.get('id')
      dispatch(actions.fetchUsersSites(currentUserId))
    }
  }, [user]); 

  return (
    return <SitesTable sites={sites}/>
  )

}

比較するpropがオブジェクトや配列の場合は useDeepCompareEffect の代わりに useEffect .