3
votes

L'état du composant ReactJS ne se met pas à jour lorsqu'une valeur du tableau d'état est modifiée

Dans mon composant React, je souhaite que mon état se mette à jour automatiquement sans recharger la page. J'utilise la méthode lodash.iseqaual pour comparer le changement d'état, mais cela ne met pas à jour l'état.

Voici mon composant:

import React, { Component } from "react";
import { Router, Route, Switch } from "react-router-dom";
import Header from "./components/Header_Footer/Header";
import Footer from "./components/Header_Footer/Footer";
import Home from "./components/Home";
import createBrowserHistory from "history/createBrowserHistory";
const history = createBrowserHistory();

class App extends Component {
  render() {
    return (
      <Router history={history}>
        <React.Fragment>
          <Header />
          <Switch>
            <Route exact path="/" component={Home} />
          </Switch>
          <Footer />
        </React.Fragment>
      </Router>
    );
  }
}

export default App;

Le lodash.isequal dans la méthode componentDidUpdate () ne met pas à jour mon état.

J'ai également essayé la logique ci-dessous dans componentDidUpdate:

import React, { Component } from "react";
import Sidebar from "./Sidebar";
import Details from "./details";

class Home extends Component {

  render() {
    return (
      <div className="container container_padding">
        <div className="row">
          <Sidebar />
          <Details />
        </div>
      </div>
    );
  }
}

export default Home;


4 commentaires

N'utilisez pas componentDidUpdate , vous pouvez utiliser componentWillReceiveProps ou getderivedState si vous utilisez les dernières versions.


@Justcode componentWillReceiveProps ne fait pas non plus la chose. Ma version de réaction est 16


veuillez créer un lien stackblitz pour reproduire le problème, avec des exemples de données


@ Justcode Je ne suis pas en mesure de créer un lien stackblitz, car l'appel d'API dusring dit: net :: ERR_SSL_PROTOCOL_ERROR . J'ai un serveur AWS EC2, d'où j'appelle mon API


4 Réponses :


0
votes

Je suppose que vous avez une erreur de syntaxe selon les Lodash Docs , vous devez ajouter un trait de soulignement avant la fonction.

Essayez de faire comme suit:

if (!_.isEqual(prevState.activeData, this.state.activeData)) {
      this.getActiveData();
    }

Veuillez également vérifier que deux tableaux sont uniques ou non et que la comparaison est en cours ou non. C'est là que réside votre problème.


1 commentaires

J'ai essayé ça. Mais la méthode componentDidUpdate () n'est pas appelée. Je fais console.log ("update"), et il ne s'imprime que 2 fois. Si la valeur dans la base de données est modifiée et que l'état est mis à jour, il ne détecte pas la mise à jour. Cela n'a pas aidé.



0
votes
 you can also use the lodash package from this 
 https://www.npmjs.com/package/lodash

 $ npm i --save lodash        

 import isEqual from "lodash/isEqual";

 componentDidUpdate(prevProps, prevState) {
   if (!isEqual(prevState.activeData, this.state.activeData)) {
      this.getActiveData();
   }
 }

2 commentaires

La méthode isEqual fonctionne correctement, vous devez changer la méthode componentDidUpdate () de la méthode getSnapshotBeforeUpdate () car la méthode componentDidUpdate (prevProps, prevState) s'exécute après la mise à jour de l'état afin que prevState ait la même valeur que celle qui a le this.state.activeData


getSnapshotBeforeUpdate (prevProps, prevState) {if (! isEqual (prevState.activeData, this.state.activeData)) {this.getActiveData (); } return null; } utilisez cette méthode au lieu de componentDidUpdate (prevProps, prevState)



0
votes
isEqual method is working Properly, You have need to change componentDidUpdate() method from getSnapshotBeforeUpdate() method because componentDidUpdate(prevProps, prevState) method execute after update the state so prevState having the same value which are having the this.state.activeData.

getSnapshotBeforeUpdate(prevProps, prevState) {
    if (!isEqual(prevState.activeData, this.state.activeData)) {
      this.getActiveData();
    }
    return null;
  }

12 commentaires

J'ai fait ça. Mais la console dit - index.js: 1446 Attention: Active: getSnapshotBeforeUpdate () doit être utilisé avec componentDidUpdate (). Ce composant définit getSnapshotBeforeUpdate () uniquement. et l'état n'est pas mis à jour.


La méthode getSnapshotBeforeUpdate () fait partie de react: 16.3, veuillez vérifier la version de react.


Une raison pour laquelle cela ne fonctionne pas? if (prevState.activeData! == this.state.activeData) {this.getActiveData ();}


Si activeData ayant l'objet à l'intérieur de l'objet et du tableau multiples, alors! == signe ne peut pas correspondre à la valeur avec plusieurs objets et tableaux, il affichera toujours le différent et correspondra également à la référence de cette propriété. tout comme activeData: {id: 2323, users [{userId: "323", name: '' "xyz", children: {}}, {userId: "323", name: '' "xyz", children: { }}]}


Ok, alors comment vais-je gérer le changement d'état, même lodash isEqual n'est pas non plus efficace ici.


utilisez-vous getActiveData () pour mettre à jour activeData à partir de l'API?


Oui, j'ai créé cette fonction pour l'appel d'API


première exécution de getActiveData () à partir de componentDidMount () pendant ce temps activeData sera nul après l'exécution, il aura la valeur mais je ne suis pas en mesure de savoir comment mettre à jour la valeur du nom dans activeData et où changer?


les données proviennent de l'api qui est créée dans Django / PostgreSQL. Si, par exemple, je change manuellement le champ de nom dans la base de données ou si je mets à jour l'enregistrement à partir du panneau d'administration, la valeur est modifiée et cette valeur modifiée doit être reflétée.


si vous modifiez la valeur du panneau d'administration ou de la base de données, vous devez actualiser l'interface utilisateur du frontend, car l'interface utilisateur ne sait pas que l'administrateur a changé la valeur du champ ou l'état activeData n'est pas mis à jour dans le composant actif. componentDidUpdate () n'est pas une bonne solution pour mettre à jour l'état car il ne s'exécutera pas pour exp: - this.state.activeData = [] après l'exécution de getActiveData () activeData Sate sera mis à jour pour ce temps this.state et prev.state avoir les mêmes données donc il ne s'exécutera pas. si vous utilisez getSnapshotBeforeUpdate (), il ne s'exécutera qu'une seule fois.


pour exp: - après l'exécution de getActiveData (), les données this.sate.active se mettront à jour puis appelleront getSnapshotBeforeUpdate () car this.sate.activeData et prev sate seront différents mais avant la deuxième exécution de getActiveData () admin don ' Si des modifications sont enregistrées, les deux états seront les mêmes, alors ce getSnapshotBeforeUpdate () ne sera pas exécuté même si l'administrateur modifie le champ.


Donc getSnapshotBeforeUpdate () ne sera jamais appelé pour un tableau d'objets, si une valeur est modifiée ou s'il y a un nouvel enregistrement? est-ce ce que cela signifie?



0
votes

getActiveData à l'intérieur de componentDidUpdate ne sera appelé qu'une seule fois, la première fois lorsque componentDidUpdate se produira, et il ne sera plus jamais appelé car prevState.activeData code> ne changez jamais.

vous pouvez essayer l'inverse, déclenchez getActiveData () sur componentDidUpdate et componentDidUpdate , utilisez shouldComponentUpdate pour décider que le composant doit être mis à jour ou non, voici le code

componentDidMount() {
    this.getActiveData();
}

shouldComponentUpdate(nextProps, nextState){
   return !isEqual(nextState.activeData, this.state.activeData)
}

componentDidUpdate() {
    this.getActiveData();
}


3 commentaires

Essayé, mais maintenant le this.getActiveData (); n'est jamais mis à jour. Je ne vois aucun enregistrement. Il continue à se charger.


@ReemaParakh désolé, j'ai oublié de retourner vrai, mettez simplement à jour la réponse, pouvez-vous réessayer


Pourriez-vous s'il vous plaît vérifier ma question mise à jour. J'ai essayé d'expliquer avec un exemple d'exemple, car shouldComponentUpdate () ne met pas à jour la valeur.