1
votes

Le composant enfant ne se rend pas, mais le composant parent le fait. Comment faire un rendu de composant enfant?

Le composant parent effectue un rendu lors de la réception de nouveaux accessoires, mais son composant enfant ne le rend pas. Les composants enfants ne sont rendus que pour la première fois et ne sont jamais rendus ni ne reçoivent d'accessoires du magasin redux

Je reçois des données mises à jour du magasin redux dans le composant Parent, mais pas dans les composants enfants. Les composants enfants ne reçoivent des données du magasin redux que lorsqu'ils sont rendus pour la première fois

Mon composant parent Home.js

L'objet seaFCLJSON ressemble à ceci const seaFCLJSON = {"rates": {"sort": "plus rapide", "someOther": "someOtherValues"}};

lorsque le magasin redux est mis à jour, seaFCLJSON regarde comme ça const seaFCLJSON = {"rates": {"sort": "moins cher", "someOther": "someOtherValues"}};

class FCLContainer extends Component {
  state = {
    seaFCLJSON: {}
  };
  componentDidMount = () => {
    this.setState({ seaFCLJSON: this.props.seaFCLJSON });
  };

  componentWillReceiveProps = nextProps => {
    console.log("outside state value: ", this.state.seaFCLJSON);
    if (this.state.seaFCLJSON !== nextProps.seaFCLJSON) {
      this.setState({ seaFCLJSON: nextProps.seaFCLJSON });
      console.log("inside state value: ", this.state.seaFCLJSON);
    }
  };


  render() {
    const { seaFCLJSON } = this.state;
    console.log("rendering .. parent props: ", this.props.fclJSON);
    console.log("rendering .. redux store props: ", this.props.seaFCLJSON);

    return (
      <>
        <div className="home-result-container">
          <div>
          <h5>This child component never rerenders :(</h5>
          </div>
        </div>
      </>
    );
  }
}

const mapStateToProps = state => {
  return {
    seaFCLJSON: state.route.seaFCLJSON
  };
};

export default connect(
  mapStateToProps,
  actions
)(FCLContainer);

isEmpty.js

export const isEmpty = obj => {
  return Object.entries(obj).length === 0 && obj.constructor === Object;
};

Mon composant enfant FCLContainer.js

class Home extends Component {
state = {
    seaFCLJSON: {}
  };

componentDidMount = () => {
     this.setState({ seaFCLJSON: this.props.seaFCLJSON });
  };

 componentWillReceiveProps = nextProps => {
    if (this.state.seaFCLJSON !== nextProps.seaFCLJSON) {
      this.setState({ seaFCLJSON: nextProps.seaFCLJSON });
    }
  };

 render() {
    const { seaFCLJSON } = this.props;
 return (
       <>
    {!isEmpty(seaFCLJSON) && seaFCLJSON.rates && seaFCLJSON.rates.fcl ? (
          <FCLContainer fclJSON={seaFCLJSON} />
        ) : null} //it never rerenders upon getting updated data from redux store

    <h5>{JSON.stringify(seaFCLJSON.rates && seaFCLJSON.rates.sort)}</h5> //it rerenders everytime upon getting updated data from redux store
       </>
     );
  }
}

const mapStateToProps = state => {
  return {
    seaFCLJSON: state.route.seaFCLJSON
  };
};

export default connect(
  mapStateToProps,
  actions
)(Home);

Je ne sais pas s'il y a des problèmes dans le composant Parent ou des problèmes dans le composant enfant. componentWillReceiveProps est appelé dans le composant parent mais pas dans le composant enfant. Veuillez ignorer tout point-virgule ou accolade manquant car j'ai omis certains codes inutiles. Edit 1: Je viens de dupliquer la valeur des accessoires vers l'état juste à des fins de débogage.

J'apprécierai votre aide. Merci.

Modifier 2 : je changeais directement un objet dans les actions redux. C'est la raison pour laquelle le CWRP n'a pas été renvoyé. C'était le problème. Pour en savoir plus, consultez ma réponse ci-dessous.


0 commentaires

4 Réponses :


0
votes

componentWillReceiveProps sera obsolète dans react 17, utilisez plutôt componentDidUpdate , qui est appelé immédiatement après la mise à jour Essayez quelque chose comme ceci:

componentDidUpdate(prevProps, prevState) {
    if (this.prevProps.seaFCLJSON !== this.props.seaFCLJSON) {
      this.setState({ seaFCLJSON: this.props.seaFCLJSON });
    }
  };


3 commentaires

Je l'ai essayé. Cela n'a pas résolu mon problème. Il n'a pas été invoqué. Il n'est invoqué que pour la première fois et ne l'est jamais pour les accessoires mis à jour


@blueseal pouvez-vous créer un sandbox de code avec le code?


désolé j'ai essayé de le reproduire mais je n'ai pas pu, plus tard je l'ai abandonné car mon projet était énorme.



0
votes

En premier lieu, il est absolument inutile de dupliquer la valeur des accessoires vers l'état, quelle en est la signification? Totalement inutile, gardez-le simplement dans les accessoires

À propos de votre problème - très probablement cette condition ne correspond pas, c'est pourquoi le composant enfant ne se déclenche pas

!isEmpty(seaFCLJSON) && seaFCLJSON.rates && seaFCLJSON.rates.fcl

le vérifier dans le débogueur p >


2 commentaires

Il est déjà tard dans la nuit. Je vais l'essayer demain et vous le faire savoir .. merci!


Je viens de dupliquer la valeur des accessoires vers l'état juste à des fins de débogage. if (! isEmpty (seaFCLJSON) && seaFCLJSON.rates && seaFCLJSON.rates.fcl) {console.log ("tout est otay");} il affiche "tout est otay" à la console



0
votes

Pour autant que je sache, votre problème est que vous transmettez ce qui suit à votre composant enfant:

<FCLContainer seaFCLJSON={seaFCLJSON} />

Mais vous supposez que vous recevez un accessoire appelé 'seaFCLJSON': p >

 componentDidMount = () => {
this.setState({ seaFCLJSON: this.props.seaFCLJSON });

};

Vous devriez changer votre code en:

<FCLContainer fclJSON={seaFCLJSON} />

En dehors de cela, comme @Paul McLoughlin déjà mentionné, vous devriez utiliser le prop directement au lieu de l'ajouter à votre état.


6 commentaires

Je n'ai pas besoin de transmettre des accessoires à mon composant enfant du parent, car j'obtiens les valeurs mises à jour du magasin redux (uniquement pour le premier rendu). Je viens de passer le prop fclJSON au composant enfant à des fins de débogage. Je ne sais pas pourquoi le composant enfant ne reçoit pas les données mises à jour du magasin redux


Je peux obtenir des accessoires mis à jour du parent dans le composant enfant. Mais une idée de la raison pour laquelle l'enfant ne reçoit pas les données mises à jour du magasin Redux mais que le parent obtient la même chose? Dans mes projets réels, les composants enfants ont leurs propres composants enfants, je devrais donc éviter le forage d'accessoires.


Autant que je sache, componentWillReceiveProps ne sera pas appelé si this.setState est utilisé pour modifier l'état ou si le composant est monté. Si votre condition de rendu (pour une raison quelconque) dans le composant parent passe de vrai à faux et inversement, le composant est remonté et componentWillReceiveProps n'est jamais appelé. Voir reactjs.org/docs/react-component.html Aussi je supprimerais tous les le code de journalisation passe simplement les données du parent à l'enfant (sans connecter l'enfant à l'état redux) et assurez-vous de rendre certains des accessoires dans les enfants.


Eh bien, avez-vous un référentiel ou quelque chose comme ça? Cela devrait en fait être un cas assez facile, mais j'ai l'impression de manquer certaines informations. Tant que le fournisseur Store encapsule ces composants, la connexion à partir d'enfants devrait poser problème.


J'ai supprimé la condition de rendu du composant parent et l'ai déplacée vers le composant enfant. Mais toujours, je ne reçois pas les données mises à jour du magasin. J'essaierai un peu plus de débogage puis je vous ferai savoir et vous inviterai probablement à mon repo. Merci pour l'aide :)


Ok, dis-moi comment ça s'est passé. Bien sûr, si vous m'invitez, je vais y jeter un coup d'œil. Je vous en prie!



0
votes

J'ai trouvé que le problème était de muter directement l'objet dans les actions. Je savais seulement que state ne devrait pas être directement muté dans la class ou à l'intérieur du reducer . J'ai changé les actions où je changeais directement un objet, puis je l'ai enregistré dans le magasin redux via dispatch , puis j'ai reçu les accessoires mis à jour dans CWRP. Cela m'a vraiment pris beaucoup de temps à comprendre. Ce genre de problème est difficile à découvrir, du moins pour moi. Je suppose que j'obtiens cela de https://github.com/uberVU/react-guide/ issues / 17

Une leçon que j'ai apprise: Ne jamais muter directement un objet

J'ai changé cela

//FCL sort by faster
export const sortByFasterFCLJSON = () => async (dispatch, getState) => {
  let seaFCLJSON = getState().route.seaFCLJSON;
  if (!seaFCLJSON.rates) return;
  seaFCLJSON.rates.fcl = _.orderBy(
    seaFCLJSON.rates.fcl,
    ["transit_time"],
    ["asc"]
  );

  // seaFCLJSON.rates.sort = "Faster"; //this was the main culprit, got lost

  seaFCLJSON = {
    ...seaFCLJSON,
    rates: { ...seaFCLJSON.rates, sort: "Faster" }
  };

  dispatch({ type: SET_SEA_FCL_JSON, payload: seaFCLJSON });
};

à ceci

//FCL sort by faster
export const sortByFasterFCLJSON = () => async (dispatch, getState) => {
  let seaFCLJSON = getState().route.seaFCLJSON;
  if (!seaFCLJSON.rates) return;
  seaFCLJSON.rates.fcl = _.orderBy(
    seaFCLJSON.rates.fcl,
    ["transit_time"],
    ["asc"]
  );

  seaFCLJSON.rates.sort = "Faster"; //this is the main culprit

  dispatch({ type: SET_SEA_FCL_JSON, payload: seaFCLJSON });
};

le pouvoir de ne pas muter les données

Remarque: Dépannage Redux


0 commentaires