1

I am trying to play around with react's child to parent communication, i am passing three buttons which has unique ids, I want to simply display the values after increment button is clicked. On first click, every button does increment fine, however, after second click on any button it gives

Cannot read property 'value' of undefined

. I am not sure what is happening after first click.

    let data = [
      {id: 1, value: 85},
      {id: 2, value: 0},
      {id: 3, value: 0}
    ]

    class Counter extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          counter: 1,
          data: this.props.data
        }
      }


      componentWillReceiveProps(nextProps) {
        if(nextProps !== this.state.data) {
          this.setState({data: nextProps})
        }
      }

       handleClick(id) {
        this.props.increment(id, 
          this.state.data[id-1].value = this.state.data[id-1].value + 
          this.state.counter);
      }

      render() {
        return (
           <div>
              {data.map(data => {
                return (
                  <div key={data.id}>
                    {data.value}
                    <button onClick={() => this.handleClick(data.id)}>+</button>
                  </div>
                )
              })}
           </div>
        )
      }

    }


    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          data
        }
      }

      onIncrement(id, newValue) {
        this.setState((state) => ({
          data: state.data[id-1].value = newValue
        }))
      }

      render() {
        return (
          <div>
           <Counter data={this.state.data} increment={this.onIncrement.bind(this)}/>
          </div>
        )
      }
    }

    ReactDOM.render(
      <App />,
      document.querySelector("#root")
    )
3
  • bro you are trying to access undefined value here this.state.data[id-1] you need to create object of this value if you want to read value this.state.data[id-1] = {} then assign value Commented Apr 3, 2019 at 10:10
  • maybe use nextProps.data instad of nextProps when you setState({data:nextProps}) Commented Apr 3, 2019 at 10:53
  • @ivica.moke, I tried that too, that makes no difference. Commented Apr 3, 2019 at 10:54

4 Answers 4

1

At this sentence:

this.props.increment(id, 
      this.state.data[id-1].value = this.state.data[id-1].value + 
      this.state.counter);

You are doing id-1, i think you don't need that, just [id]. In case you are click button with id 1 your are trying to increment value of 1 - 1 and you haven't any data with id 0

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

1 Comment

Data is an array and i m pulling the index of the object and then assigning the value, if id is 1 then this.state.data[0].value means 85 right ?, so, initially it increments but after that it doesn't, I also tried with only [id] and setting back global data ids from 0 to 2 but giving the same error.
1

The problematic thing in your code is this line

this.state.data[id-1].value = this.state.data[id-1].value + this.state.counter);

what exactly you want to do here ? because you have 3 index 0,1,2 and you are out of index the it's undefined and you got error mention your requirement here.

your code using state in useless manner and i just optimize your code in a good way. Tip: do not use state-full component where not required use function component. it's working fine and serve according to your need.

    const Counter = (props) => {
    return (
        <div>
            {props.data.map(d => {
                return (
                    <div key={d.id}>
                        {d.value}
                        <button onClick={() => props.increment(d.id, (d.value + 1))}>+</button>
                    </div>
                )
            })}
        </div>
    )
}
class App extends React.Component {

    state = {
        data: [
            { id: 1, value: 85 },
            { id: 2, value: 0 },
            { id: 3, value: 0 }
        ]
    }
    onIncrement = (id, newValue) => {
        debugger
        var newdata = [...this.state.data];
        var d = { ...newdata[id - 1] };
        d.value = newValue;
        newdata[id - 1] = d;
        this.setState({ data: newdata })
    }

    render() {
        return (
            <div>
                <Counter data={this.state.data} increment={this.onIncrement} />
            </div>
        )
    }
}

ReactDOM.render(
    <App />,
    document.querySelector("#root")
)

1 Comment

I simply want to increment values assigned to each buttons independently, I don't understand how i m going out of index, keeping this in mind, i am decrementing id to be able to be in the index 0, 1, 2 of the data array. Correct me if i am wrong.
0
import React from 'react';

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 1,
      data: this.props.data
    };
  }

  handleClick(id, index) {
    this.props.increment(
      id,
      (this.props.data[id - 1].value =
        this.props.data[id - 1].value + this.state.counter), index
    );
  }

  render() {
    return (
      <div>
        {this.props.data.map((data
         , index) => {
          return (
            <div key={data.id}>
              {data.value}
              <button onClick={() => this.handleClick(data.id, index)}>+</button>
            </div>
          );
        })}
      </div>
    );
  }
}

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

  onIncrement(id, newValue, index) {
    let {data} = this.state;
  data[index].value = newValue;
    this.setState({
      data
    });
  }

  render() {
    console.log(this.state.data)
    return (
      <div>
        <Counter
          data={this.state.data}
          increment={this.onIncrement.bind(this)}
        />
      </div>
    );
  }
}

please take a look you are doing state updation in wrong way

Comments

0

I found the issue, you have wrongly implemented componentWillReceiveProps and onIncrement , i have corrected these two functions :

onIncrement(id, newValue) {
   let data = this.state.data;
   data[id-1].value = newValue;
   this.setState({data})
}

componentWillReceiveProps(nextProps) {
    if(nextProps.data !== this.props.data) {
      this.setState({data: nextProps.data})
    }
}

Also see the working demo here : https://repl.it/@VikashSingh1/TemporalReliableLanserver

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.