shekwo
shekwo

Reputation: 1447

Error dynamically updating an array list in ReactJs

I am learning reactJS and so I am trying my hands on an example. This example has a form textfield that can add an item to an existing array on click of a button. I am having errors here as when I enter a text and click on the button, the array list is not updated except I try to make changes to the text entered in the textfield. This is what I am doing:

import React, { Component } from 'react';

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      currentName : '',
      arrays : ['john', 'james', 'timothy']
    }   
  }
  render() {
    const showNames =   this.state.arrays.map((thisName) => {
        const values = <li>{thisName}</li>;
        return values;
     }); 
    const getText = (e) => {
        let value = e.target.value;
        this.setState({
          currentName : value
        })
    }
    const addToUsers =  () => {
      this.state.arrays.push(this.state.currentName)
    }

    return (
      <div>
        <p>Add new name to List</p><br/>
        <form>
          <input type="text"  onChange={getText}/>
          <button type="button" onClick={addToUsers}>Add User</button> 

        </form>
        <ul>
          {showNames}
        </ul>
      </div>

    );
  }
}

export default App;

Upvotes: 0

Views: 1745

Answers (3)

coreyward
coreyward

Reputation: 80041

There are a host of things wrong with this, but your issue is likely that you need to use setState to modify state.

import React, { Component } from 'react';

class App extends Component {
  constructor(){
    super();

    this.state = {
      names: ['john', 'james', 'timothy']
    }
  }

  addToUsers = () => {
    this.setState(
      prevState => ({
        names: [...prevState.names, this.input.value]
      })
    )
  }

  render() {
    const names = this.state.names.map(
      (name, index) => <li key={index}>{name}</li>
    )

    return (
      <div>
        <p>Add new name to List</p><br/>

        <form>
          <input type="text" ref={e => this.input = e} />
          <button type="button" onClick={this.addToUsers}>Add User</button> 
        </form>

        <ul>
          {names}
        </ul>
      </div>
    )
  }
}

export default App;

This quick edit changes a few things:

  1. Uses setState for the addToUsers method
  2. Eliminate onChange tracking and pull the name directly from the input when the button is clicked
  3. Move the addToUsers method out to the component class rather than defining it on render
  4. Rename this.state.arrays to this.state.names
  5. Simplify conversion of this.state.names into list items
  6. Set key on array elements (name list items)
  7. Use prevState in setState to avoid race conditions

Upvotes: 3

Kamil Naja
Kamil Naja

Reputation: 6692

You probably must add

onChange={getText}.bind(this)

to your functions. Also change this

const addToUsers =  () => {
      this.state.arrays.push(this.state.currentName)
    }

to this

const addToUsers =  () => {
      this.setState({here put your variable})
    }

Upvotes: 0

SpoonMeiser
SpoonMeiser

Reputation: 20417

You need to make sure you update state using the setState method.

When you update arrays you are reaching into the state object and manipulating the data directly instead of using the method.

Instead try something like:

const addToUsers =  () => {
  const newArray = this.state.arrays.concat([this.state.currentName]);
  this.setState({
    arrays: newArray
  });
}

Upvotes: 2

Related Questions