2
votes

La mise à jour du contexte de réaction à partir du composant consommateurDidMount provoque des rendus infinis

J'essaye une gestion d'état dans React en utilisant l'API de contexte; ce que je veux réaliser, c'est que lorsque j'atteins une route spécifique, je charge les données du serveur, je les stocke dans le contexte et les affiche dans la page elle-même. Cela provoque une boucle infinie où la requête au serveur est répétée à plusieurs reprises (et ne s'arrête jamais).

J'essaie d'utiliser des composants d'ordre supérieur pour la logique du fournisseur et du consommateur:

import React, { Component } from 'react';

import RequestStatus from './RequestStatus';
import dataCtx from './contexts/DataContext';

class DataList extends Component {
  async componentDidMount() {
    const { getData } = this.context;
    await getData();
  }

  render() {
    const { data, requestStatus } = this.context;
    return (
      {/* display the data here */}
    );
  }
}

DataList.contextType = dataCtx;

export default DataList;

le fournisseur est le composant App lui-même:

import React, { Component } from 'react';

import RequestStatus from './RequestStatus';
import { dataContextConsumer } from './contexts/DataContext';

class DataList extends Component {
  async componentDidMount() {
    const { dataCtx: { getData } } = this.props;
    await getData();
  }

  render() {
    const { dataCtx: { data, requestStatus } } = this.props;
    return (
      {/* display the data here */}
    );
  }
}

export default dataContextConsumer(DataList);

et voici le consommateur qui provoque la boucle:

import React, { Fragment } from 'react';

import { dataContextProvider } from './contexts/DataContext';
import { userContextProvider } from './contexts/UserContext';

import AppRoutes from './AppRoutes';

function App() {
  return (
    <Fragment>
      <main>
        <AppRoutes />
      </main>
    </Fragment>
  );
}

export default userContextProvider(dataContextProvider(App));


0 commentaires

3 Réponses :


0
votes

la boucle de requête se produit car le composant DataList est rendu de nouveau, en appelant ComponentDidMount , qui appelle getData () après chaque rendu.

/ p>

Un composant effectue le rendu en cas de modification des accessoires ou de l'état du composant.

getData () définit la propriété d'état requestStatus (c'est pourquoi l'ensemble de votre application est re-rendu) qui est un accessoire de DataList - provoquant un nouveau rendu de DataList .

vous ne devez pas utiliser requestStatus comme accessoire de DataList car vous obtenez cela à partir du contexte de toute façon.


1 commentaires

Je ne suis pas sûr de ce que vous voulez dire, requestStatus n'est pas un accessoire de DataList , il fait partie du contexte tout comme data . De plus, selon les documents de réaction, componentDidMount ne doit être appelé que lorsque le composant est ajouté à l'arborescence DOM, pas à chaque fois qu'il est rendu. Le composant quitte-t-il le DOM à un moment donné?



0
votes

Cela peut être dû au fait que votre fonction de niveau fournisseur ( dataContextProvider ) getData a le même espace de noms que votre fonction que vous importez depuis .. / Api .

Et puis je crois que lorsque la ligne suivante const data = await getData (); s'exécute dans le bloc de code ci-dessous, elle appelle en fait la fonction getData du fournisseur, donc provoquant une boucle.

  async getData() {
      this.setState({ requestStatus: RequestStatus.RUNNING });
      try {
        const data = await getData();
        this.setState({ data, requestStatus: RequestStatus.INACTIVE });
      } catch (error) {
        this.setState({ requestStatus: RequestStatus.FAILED });
      }
    }


3 commentaires

J'espérais que ce serait ça, mais ça ne semble pas être le cas .. J'obtiens toujours la boucle même avec des noms différents.


Hmm, c'est juste! Je ne sais pas ce que cela pourrait être d'autre. Tout le reste semble être bon. Je suggérerais d'éliminer peu à peu certaines complexités afin que vous puissiez préciser ce qui cause le problème. Il serait également utile de créer un sandbox avec le code de base de votre projet afin que toute personne souhaitant vous aider puisse déboguer le problème via le bac à sable.


Bonne idée sur le bac à sable, je vais le construire et éditer un lien vers celui-ci dans le message lui-même .. peut-être que cela aidera aussi à trouver le problème :)



2
votes

Ok, après avoir essayé de reproduire le problème dans un bac à sable, j'ai réalisé quel était le problème: j'enveloppais un composant parent dans un HOC dans une fonction de rendu, comme ceci:

<Route exact path="/datapage" component={requireLoggedInUser(Page)} />

qui forcé le composant DataList à être détruit + recréé à chaque fois que l'application est de nouveau rendue.


0 commentaires