Usama Abdul Razzaq
Usama Abdul Razzaq

Reputation: 803

react component state changed only once

I have two components <App /> and <CompA/>

The task I want to accomplish is,

I have a state in <App/> and an input field <CompA/> and I want to change the state of <App/> by changing the input in <CompA/>

App.js


export default function App() {
  const [containers, setContainers] = useState({
    invoiceData: null,
    containers: [
      { id: "09d4ba8a-30f1-4bf5-8b9f-ca45c497039a", containerNum: "" }
    ]
  });

  const changeContainerNum = (e, index) => {
    let current = containers;
    current.containers[index].containerNum = e.target.value;

    // current variable change on every function call
    console.log("local variable", current);
    setContainers(current);
  };
  // but state only change once
  console.log("////state", containers);

  return (
    <div>
      {containers.containers.map((container, index) => (
        <CompA
          key={container.id}
          index={index}
          changeContainerNum={changeContainerNum}
        />
      ))}
    </div>
  );
}

CompA.js



function CompA({ changeContainerNum, index }) {
  const [containerNumber, setContainerNumber] = useState("");

  return (
    <div>
      <input
        placeholder="Container Number..."
        value={containerNumber}
        onChange={(e) => {
          changeContainerNum(e, index);
          setContainerNumber(e.target.value.toUpperCase());
        }}
      />
    </div>
  );
}

export default CompA;

I want to change the containerNum property of containers state,

The Issue is

when the onChange event gets triggered the changeContainerNum(e, index) the code works fine in this function but when I assign the new changed value to the state then it updates the state only once

onChange={(e) => {
          // 👇
          changeContainerNum(e, index);
          setContainerNumber(e.target.value.toUpperCase());

        }}
      

How can I update the state on every onChange event. It will be helpful to update code here

Upvotes: 0

Views: 690

Answers (1)

Olivier Boiss&#233;
Olivier Boiss&#233;

Reputation: 18083

You should not mutate a state variable, you must instead create a new reference :

const changeContainerNum = (e, index) => {
  const containerNum = e.target.value;

  setContainers(({invoiceData, containers})=> ({
    invoiceData,
    containers: containers.map((container, idx) => 
      idx === index ? {...container, containerNum} : container
    )
  }));
};

Upvotes: 1

Related Questions