0

I tried to push a value into a state array but I get an issue TypeError: Cannot read property 'state' of undefined at this.state.rows.push(a);

Know why? I am trying to push a new value into the array after i click a button.

App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  constructor() {
    super();
    this.state = {
      name: '',
      rows: ['hello',<p>gfdfg</p>,'mello']
    }

  }

  handle(e){
    e.preventDefault();
    var a = "h";
    this.state.rows.push(a);
    alert("hello");
  }

  render() {
    return (
      <div className="App">
        Button<br/>
        <input type="submit" id="black" onClick={this.handle}/><br/>
        <p>{this.state.rows}</p>
      </div>
    );
  }
}

export default App;
1
  • mutating state is definitely not a good idea instead of pushing how about using this.setState({ }) instead of this.state.rows.push(a); Commented Jan 21, 2018 at 17:08

5 Answers 5

3

There are couple of things that are wrong here:

  1. you should NEVER change the state directly:

This is a big No No:

this.state.rows.push(a);

instead you should do something like this: this.setState({ rows : [...this.state.rows, a] })

or without ES6:

const newArray = this.state.rows.slice();
newArray.push(a);
this.setState({ rows: newArray })

You should always replace the state with a new one.

  1. this in a react component is not what you think it is, in order to make it work you can do one of two things:

a. change your method to an arrow function:

handle = (e) => {
    e.preventDefault();
    var a = "h";
    this.state.rows.push(a);
    alert("hello");
  }

b. bind this to the method:

constructor() {
    super();
    this.state = {
      name: '',
      rows: ['hello',<p>gfdfg</p>,'mello']
    }
    
    this.handle = this.handle.bind(this);

  }

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

Comments

1

the method handle does not have access to the context of the class i.e this; consider writing it as a fat arrow function

// class definition 
handle = () => {
  e.preventDefault();
  var a = "h";
  this.state.rows.push(a);
  alert("hello");
}

render() {
  // render logic
} 

Having said this, mutating the state is not a good idea, consider using setState if you want your component to re-render as a result of state change

handle = () => {
  e.preventDefault();
  let { rows } = this.state;
  var a = "h";
  rows.push(a);
  this.setState({
    rows,
  });
}

Comments

1

You are doing wrong, you have to use setState() method to push the value in the array:

handle = (e) => {
    e.preventDefault();
    var a = "h";
    let tempRows = [...this.state.rows];
    tempRows.push(a)
    this.setState({rows:tempRows})
    alert("hello");
  }

Comments

0

You have two problems.

  1. Event handlers require 'this' to be bound: https://reactjs.org/docs/handling-events.html So following this, you must either write: this.handle = this.handle.bind(this) in your contructor, or change handler to arrow function, if your build process supports transpilation of class fields.

  2. React component will only update if component props change, or component state changes. Which is done by comparing references. In your case, when you push to the array, you are mutating the state, so the new reference is never created, and component does not re-render. If you want to verify that, just put console.log(this.state.rows) below this.state.rows.push(a) and you'll see that the array has received the new value, but component does not represent it. You need to use this.setState to create a new reference for your state, like so: this.setState({ rows: [...this.state.rows, a] })

Comments

0

Another way of returning a new array from the current array with additional elements and then pushing to state is to use the concat method.

Example :

this.setState({ users: this.state.users.concat(<Additonal Items Here>)}

Comments

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.