Home > Net >  state data not changing in the render/display
state data not changing in the render/display

Time:11-08

I want to change the property amount in a state object using buttons (increment and decrement). I checked using console.log and the property's value is changing when the buttons are clicked, but the displayed number is not changing. why is that? what am I doing wrong?

here's my code: (codesandbox)

import React, { useState, useEffect } from "react";
import { Button } from "react-bootstrap";

export default function App() {
  const [data, setData] = useState({});

  useEffect(() => {
    const temp = {
      id: 1,
      name: "apple",
      amount: 10
    };
    setData(temp);
  }, []);

  const handleInc = () => {
    let temp = data;
    temp.amount  ;
    console.log("increment", temp.amount);
    setData(temp);
  };
  const handleDec = () => {
    let temp = data;
    temp.amount--;
    console.log("decrement", temp.amount);
    setData(temp);
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <label>name: {data.name}</label>
      <br />
      <label>amount: {data.amount}</label>
      <br />
      <Button onClick={handleDec}>Reduce</Button>
      <Button onClick={handleInc}>Increase</Button>
    </div>
  );
}

CodePudding user response:

let temp = data;
temp.amount  ;
setData(temp);

does not update data, as temp == data even after temp.amount .
The state setter accepts either a new object or a state update callback.
Since you are updating state using it's old value, you need a state update callback,
that returns a new object (via cloning).

setData((data)=> {
    let temp = {...data}; // or Object.assign({}, data);
    temp.amount  ;
    return temp;
}

Likewise, for decrementing.

See https://beta.reactjs.org/learn/updating-objects-in-state
and https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

CodePudding user response:

You have 2 issues here. First one is that you using object as your state and object is reference type. When you do let temp = data you just referecing the same exact "data" object using different variable (pointer) "temp". Simply speaking once you change property in one variable, it "changes" the other. Now that also means that whatever you do, temp will always be equal to data cause they are referencing the same object. So to React state it means that it never really changes in your case, when you do setState you passing the same exact reference, so React sees that nothing changed - so it doesn't trigger re-render. Hope it is clear. Fix in this case is to create a copy of object, in your case it could be simply setState({...temp})

The second issue in your case is that you are not using functional setState, which in your case is needed. The way you wrote it, might lead to bugs and unexpected behaviours, basically whenever you need to modify the state based on previous state value - you need to use functional setState. There are a lot of topics on this, let me reference just one - https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b/

In your case correct solution would be setState((prevState) => ({...prevState, amount: prevState.amount 1}))

CodePudding user response:

I think you should use Callback with useState to resolve this bug.

  const handleInc = () => {
    setData((prevState) => ({ ...prevState, amount: prevState.amount   1 }));
  };

  const handleDec = () => {
    setData((prevState) => ({ ...prevState, amount: prevState.amount - 1 }));
  };

CodePudding user response:

Take note of both of the other answers by Nice Books and Nikita Chayka they both touch on important topics that will help you avoid this issue in the future. If you want to update an object using states you need to reconstruct the entire object when you reset the object. I made a fork of your sandbox you can take a look at of a working example that should solve your issue Forked sandbox.

Also the docs reference this issue as well Doc reference.

Please let me know if you need any additional information.

  • Related