简体   繁体   中英

React Dom not updating after updating a state array

so this function updates this state array: let [Produits, setProduit] = useState(JSON.parse(Devis.produits))

 let changeQte = (id, e) => {
    let produittable = Produits;
    produittable.forEach((p) => {
      if (p.id == id) {
        p.quantityAchete = parseInt(e.target.value);
      }
    });
    setProduit(produittable);  
  };

the array did update without any problem but the changes aren't getting re-rendered

  {console.log('rendering') ,Produits.map((p) => (
            <div key={p.id} className="product_column flex_center">
              <div className="productItem">{p.nom}</div>
              <div className="productItem">{p.category}</div>
              <div className="productItem">{p.prix_vente} DA</div>
              <input
                onChange={(e) => changeQte(p.id, e)}
                type="number"
                name="qte"
                value={p.quantityAchete}
              />

as you can see i'm loggin to the console to check if that line is getting executed and it does ! but the values rendered doesn't update !

Don't mutate state , do this instead:

 let changeQte = (id, e) => {
    setProduit(existing => existing.map(c => c.id === id ? {...c,quantityAchete: parseInt(e.target.value)} : c))
  };   

These lines:

    // this line just sets produittable to the same reference as Produits.
    // so now produittable === Produits, it's essentially useless
    let produittable = Produits;
    produittable.forEach((p) => {
      if (p.id == id) {
        // you are mutating 
        p.quantityAchete = parseInt(e.target.value);
      }
    });
    // because produittable === Produits, this doesn't do anything
    setProduit(produittable);  

In addition to what Adam said, besides not modifying the state directly, the reason you're not seeing any changes is because the component only gets rerendered when the state actually changed. And to know whether the state changed, react makes a shallow comparison between the two states. Since you modified the state directly, the reference remains the same and as such your component isn't rerendering.

To expand on Adam's answer, you can also clone the current state Produits and assign it to the local variable produittable and have the state update be recognized.

So instead of this:

let produittable = Produits;

You could simply clone it like so, with the spread operator:

let produittable = [...Produits];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM