121 votes

le composant de réaction de redondance lorsque l'hélice change

Je suis en train de séparer une présentation des composants à partir d'un composant conteneur. J'ai un SitesTable et SitesTableContainer. Le conteneur est responsable du déclenchement redux actions pour aller chercher les sites appropriés en fonction de l'utilisateur actuel. Le problème est que l'utilisateur actuel est récupérée de manière asynchrone, après le composant conteneur est rendu au départ. Cela signifie que le composant conteneur ne sait pas qu'il a besoin de ré-exécuter le code de son componentDidMount fonction qui permettrait de mettre à jour les données à envoyer à l' SitesTable. Je pense que j'ai besoin alors rendre à nouveau le composant conteneur lors de l'un de ses accessoires(utilisateur) des changements. Comment puis-je faire cela correctement?

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);

144voto

QoP Points 12702

Vous devez ajouter une condition dans votre componentWillReceiveProps méthode.

C'est comment votre composant doit ressembler à

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 property, 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))
  }  
}

Mise à JOUR de React (17)

Ressemble componentWillReceiveProps va être supprimé à Réagir 17. Vous pouvez utiliser componentDidUpdate au lieu de componentWillReceiveProps pour obtenir la même chose.

L'autre exemple est l'utilisation de fast-deep-equal au lieu de JSON.stringify() pour comparer les objets.

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))
  }  
}

42voto

ob1 Points 500

ComponentWillReceiveProps() va être obsolète dans le futur en raison de bugs et d'incohérences. Une solution de rechange pour le re-rendu d'un composant sur les accessoires changement est d'utiliser ComponentDidUpdate() et ShouldComponentUpdate().

ComponentDidUpdate() est appelé chaque fois que les mises à jour ET si ShouldComponentUpdate() retourne true (Si ShouldComponentUpdate() n'est pas défini, il retourne true par défaut).

shouldComponentUpdate(nextProps){
    return nextProps.changedProp !== this.state.changedProp;
}

componentDidUpdate(props){
    // Desired operations: ex setting state
}

Ce même comportement peut être réalisée en utilisant seulement l' ComponentDidUpdate() de méthode, y compris l'instruction conditionnelle à l'intérieur.

componentDidUpdate(prevProps){
    if(prevProps.changedProp !== this.props.changedProp){
        this.setState({          
            changedProp: this.props.changedProp
        });
    }
}

Si l'on tente de définir l'état, sans conditionnel ou sans la définition d' ShouldComponentUpdate() le le composant infiniment re-rendre

4voto

Shen Lance Points 1059
 componentWillReceiveProps(nextProps) { // your code here}
 

Je pense que c'est l'événement dont vous avez besoin. componentWillReceiveProps déclenche chaque fois que votre composant reçoit quelque chose via des accessoires. À partir de là, vous pouvez faire votre vérification, puis faire ce que vous voulez.

4voto

TameBadger Points 1076

Je recommande d'avoir un oeil à cette réponse de la mine, et de voir s'il est pertinent pour ce que vous faites. Si je comprends bien votre vrai problème, c'est que vous tout simplement pas à l'aide de votre action asynchrone correctement et mise à jour de la redux "store", qui mettra automatiquement à jour votre composant avec de nouveaux accessoires.

Cette section de votre code:

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

Ne devrait pas être le déclenchement d'un composant, il doit être manipulé après l'exécution de votre première demande.

Jetez un oeil à cet exemple de 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))
    );
  };
}

Vous n'avez pas nécessairement à utiliser redux-thunk, mais il va vous aider à raisonner sur des scénarios de ce genre et écrire le code pour le match.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X