Jay_Placeholder
Jay_Placeholder

Reputation: 43

React hook useState method updates array unexpectedly

I am learning React hook and tried to update an array value. What I want to achieve is when the button is clicked, the name and the counter of the first element perform the +1 operation. However, the code performs the operation twice instead. So the button shows

Initial: Click 0 FirstArgument

Click 1: Click 1 FirstArgument1

Click 2: Click 3 FirstArgument111

Click 3: Click 5 FirstArgument11111

...

Here is the code snipe:

import React, { useState } from "react";

function HookCount() {
  const initState = [
    {
      counter: 0,
      name: "FirstArgument",
    },
    "SecondArgument",
  ];

  const [variable, setCount] = useState(initState);

  const setStateFun = () => {
    setCount((prevVariable) => {
      let updateList = [...variable];
      updateList[0].name = prevVariable[0].name + 1;
      updateList[0].counter = prevVariable[0].counter + 1;
      updateList[1] = prevVariable[1];
      return updateList;
    });
  };

  return (
    <div>
      <button onClick={setStateFun}>
        Click {variable[0].counter} {variable[0].name}
      </button>
    </div>
  );
}

export default HookCount;

The questions that I have are:

  1. Why the code behaves like that. What I did wrong or what is the proper way to achieve this.

  2. If I replace let updateList = [...variable]; with let updateList = prevVariable; the state does not change anymore. Why can't we use prevVariable instead of spread the array here?

Upvotes: 0

Views: 91

Answers (1)

Brandon Mitchell
Brandon Mitchell

Reputation: 369

I don't see setCount or variable defined anywhere it your code, so I cannot guess how you implemented them. However, setStateFun is just overcomplicated.

By using the functional setState, you already have access to prevVariable. To perform the increment, it can be simplified like so:

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [variable, setCount] = useState([
    {
      counter: 0,
      name: "FirstArgument"
    },
    "SecondArgument"
  ]);

  const setStateFun = () => {
    setCount(prevVariable => [
      {
        counter: prevVariable[0].counter + 1,
        name: prevVariable[0].name + 1
      },
      prevVariable[1]
    ]);
  };

  return (
    <div>
      <button onClick={setStateFun}>
        Click {variable[0].counter} {variable[0].name}
      </button>
    </div>
  );
}

See it here:

Edit nameless-pine-4hsbj

Upvotes: 1

Related Questions