How to increment the value of an object within state React

Issue

So I have this component called counters where the state looks something like this

state = {
    counters: [
      { id: 1, value: 0 },
      { id: 2, value: 3 },
      { id: 3, value: 0 },
      { id: 4, value: 0 },
    ],
  };
  

And I’m trying to increment the value every time a corresponding button is clicked. This is the function I wrote for it.

  handleIncrement = (counter) => {
    const counters = [...this.state.counters];
    const index = counters.indexOf(counter);
    counters[index] = { ...counter };
    counters[index].value++;
    this.setState({ counters });
  };

It doesn’t work. And here are some additional observations.

  1. When I console.log the local counters object (copied from state.counters) it returns an additional row at the end with id: -1 and value: NaN
  2. The variable counter (thats being passed as a parameter) is from a child component. It’s supposed to return 0 if the first button is clicked, 1 if the second button is clicked and so on. When I console.log it it seems to be returning the correct values.

by the looks of it, the problem seems to lie in the line

const index = counters.indexOf(counter);

As the value of index is always returned as -1.

Solution

You can use the index for updating the corresponding record in the array.

const idx = this.state.counters.findIndex((counter) => counter.id === id);

Complete implementation:-

import React from "react";
import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counters: [
        { id: 1, value: 0 },
        { id: 2, value: 3 },
        { id: 3, value: 0 },
        { id: 4, value: 0 }
      ]
    };
  }

  handleClick = (id) => {
    const idx = this.state.counters.findIndex((counter) => counter.id === id);
    const counters = [...this.state.counters];
    counters[idx] = { ...counters[idx], value: counters[idx].value++ };
    this.setState(counters);
  };

  render() {
    return (
      <div>
        {this.state.counters.map((counter) => (
          <div>
            <button onClick={() => this.handleClick(counter.id)}>
              Button {counter.id}
            </button>
            <span>Value {counter.value}</span>
            <hr />
          </div>
        ))}
      </div>
    );
  }
}

Codesandbox – https://codesandbox.io/s/musing-black-cippbs?file=/src/App.js

Answered By – Sarun UK

Answer Checked By – Timothy Miller (AngularFixing Admin)

Leave a Reply

Your email address will not be published.