6

How can I update a single element in a state array? Here is the code that I am currently using:

const Cars = props => {
  const [cars, setCars] = React.useState(["Honda","Toyota","Dodge"])

  const handleClick1 = () => { setCars[0]("Jeep") }
  const handleClick2 = () => { setCars[1]("Jeep") }
  const handleClick3 = () => { setCars[2]("Jeep") }

  return (
    <div>
      <button onClick={handleClick1}>{cars[0]}</button>
      <button onClick={handleClick2}>{cars[1]}</button>
      <button onClick={handleClick3}>{cars[2]}</button>
    </div>
  )
};

When I click one of the rendered buttons, I get Uncaught TypeError: setCars[0] is not a function at handleClick1.

I know how to do this in a React Class, but how can I do this with React Hooks?

2 Answers 2

14

I suggest you map through your cars in order to render them - this is just overall a million times easier. From there you can apply an onClick handler to each button..

Furthermore, you should not mutate state like you are - always make a copy of state first, update the copy, then set your new state with the updated copy.

Edit: one thing that slipped my mind before was adding a key to each item when you are mapping over an array. This should be standard practice.

const { useState } = React;
const { render } = ReactDOM;

const Cars = props => {
  const [cars, setCars] = useState(["Honda", "Toyota", "Dodge"]);

  const updateCars = (value, index) => () => {
    let carsCopy = [...cars];
    carsCopy[index] = value;
    setCars(carsCopy);
  };

  return (
    <div>
      {cars && cars.map((c, i) => 
        <button key={`${i}_${c}`} onClick={updateCars("Jeep", i)}>{c}</button>
      )}
      <pre>{cars && JSON.stringify(cars, null, 2)}</pre>
    </div>
  );
};

render(<Cars />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

0

I think you should correct these lines to spot the source of error

const handleClick1 = () => { setCars[0]("Jeep") }

into

const handleClick1 = () => { cars[0]="Jeep"; setCars(cars); }

2 Comments

you are mutating state variables. It's "no-no" in React world. Re-rendering probably will run anyway(it least for class-based component setState re-render even if no changes), but once you pass this state as a prop to some child you man go in trouble.
yes i see your point, but considering the that is not the numero uno issue in question its some times better to keep it simple: Uncaught TypeError

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.