user6329530
user6329530

Reputation: 734

Changing an array item creates an unlimited nested copy of itself?

I try to set a number in an input field and keep it in a state. However when I try to set the state of the array, it doesn't get populated and when I try it with an anonymous function it creates something like

{
    "btm": {
        "btm": {
            "btm": {...}, 
            "top": 100}, 
        "top": 100}, 
    "top": 100
}

Here the code that does this:

const Numbers = (props) => {
    const [numbers, setNumbers] = useState({"btm": "1", "top": "100"});
    
    const fromNumber = (n) => {
        console.log(numbers);
        setNumbers((n) => {
            const copy = numbers;
            copy["btm"] = n;
            return copy;
        });
    }

return (
            <>
                <input variant="toolbar-input" defaultValue={numbers["btm"]} onChange={e => fromNumber(e.target.value)} />
            </>
);
}

Upvotes: 0

Views: 62

Answers (3)

Yaroslav
Yaroslav

Reputation: 110

You are using the same variable name here - const fromNumber = (n) => {... and here setNumbers((n) => {....

Also you can go with ES6 Spread Syntax and convert state update function to this:

setNumbers((prevNumbers) => ({
   ...prevNumbers,
   btm: n,
}));

Upvotes: 1

Deykun
Deykun

Reputation: 1271

You are overriding the variable n here.

const fromNumber = (n) => {
  console.log(numbers);
  setNumbers((n) => {
    const copy = numbers;
    copy["btm"] = n;
    return copy;
  });
}

Here n is a value received from the input:

const fromNumber = (n) => {

Here n is the previous state of variable numbers:

setNumbers((n) => {

So you are nesting older state in the new one.

Upvotes: 2

user13594285
user13594285

Reputation:

As you are using useState, you can do:

const Numbers = (props) => {
  const [numbers, setNumbers] = useState({ btm: "1", top: "100" });

  const fromNumber = (n) => {
    console.log(numbers);
    setNumbers({...numbers, btm: n});
  };

  return (
    <>
      <input
        variant="toolbar-input"
        defaultValue={numbers["btm"]}
        onChange={(e) => fromNumber(e.target.value)}
      />
    </>
  );
};

Note that a map has unique keys, so you can go on with ES6 Spread Syntax.

Upvotes: 3

Related Questions