最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to add to state array in React - Stack Overflow

programmeradmin4浏览0评论

I am making a simple to-do list app in React. I have 3 states, inputText (the task the user enters), triggerAnimation(to trigger animations), and tasks (the list of tasks user has entered). However I don't know how to update the tasks state (which is an array) to push the new tasks. Here is the code.

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

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      inputText: '',
      triggerAnimation: '',
      tasks: []
    }
  }

//The function triggered by button which sends the task the user has entered to the tasks array state:

  addItem() {
    document.querySelector("#textfield1").value = ""
    this.setState({ 
      triggerAnimation: 'fadein', tasks: 
      this.state.inputText 
    }) 
  }



  render() {
    //Where User enters task:
    return (
      <div className="App">
        <main>
          <div className="enterTask">
            <input type="text" className="inputclass" id="textfield1" 
              placeholder='Enter a task.' 
              onChange={event => this.setState({ 
                inputText: event.target.value })} 
              onKeyPress={event => {
                if(event.key === 'Enter') {
                  this.addItem();
                }
               }} 
             />
            <br />
            <br />
            <button className="button" 
              onClick={() => this.addItem()} data-
                toggle='fadein' data-target='list'>+
            </button>
         </div>


    <!-- Where tasks will appear: -->

         <div className="log">
           <p className='list'>
             <span class={this.state.triggerAnimation}>  
               {this.state.tasks}
             </span>
           </p>
           <button className="button">-</button>
         </div>
       </main>
     </div>
    )
  }
}  

export default App;

I am making a simple to-do list app in React. I have 3 states, inputText (the task the user enters), triggerAnimation(to trigger animations), and tasks (the list of tasks user has entered). However I don't know how to update the tasks state (which is an array) to push the new tasks. Here is the code.

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

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      inputText: '',
      triggerAnimation: '',
      tasks: []
    }
  }

//The function triggered by button which sends the task the user has entered to the tasks array state:

  addItem() {
    document.querySelector("#textfield1").value = ""
    this.setState({ 
      triggerAnimation: 'fadein', tasks: 
      this.state.inputText 
    }) 
  }



  render() {
    //Where User enters task:
    return (
      <div className="App">
        <main>
          <div className="enterTask">
            <input type="text" className="inputclass" id="textfield1" 
              placeholder='Enter a task.' 
              onChange={event => this.setState({ 
                inputText: event.target.value })} 
              onKeyPress={event => {
                if(event.key === 'Enter') {
                  this.addItem();
                }
               }} 
             />
            <br />
            <br />
            <button className="button" 
              onClick={() => this.addItem()} data-
                toggle='fadein' data-target='list'>+
            </button>
         </div>


    <!-- Where tasks will appear: -->

         <div className="log">
           <p className='list'>
             <span class={this.state.triggerAnimation}>  
               {this.state.tasks}
             </span>
           </p>
           <button className="button">-</button>
         </div>
       </main>
     </div>
    )
  }
}  

export default App;
Share Improve this question edited Feb 14, 2018 at 22:01 Tim Han 1661 silver badge12 bronze badges asked Feb 14, 2018 at 20:38 UsmanUsman 1651 gold badge1 silver badge11 bronze badges 2
  • Please fix the formattig. Thats not readable at all – Jonas Wilms Commented Feb 14, 2018 at 20:42
  • 1 Your addItem method is resetting the state of tasks as a string. You can use the spread operator. this.setState({tasks: [...this.state.task, this.state.inputText]}) – Tim Han Commented Feb 14, 2018 at 20:50
Add a comment  | 

6 Answers 6

Reset to default 9

However I don't know how to update the tasks state (which is an array) to push the new tasks.

Probably the cleanest way to "push to an array" in state is to use ES6 array spread. The best practice would also be to use the setState callback syntax to ensure the correct state is committed before you push the new task:

this.setState(prevState => ({
  tasks: [...prevState.tasks, newTask] 
}));

Seems like what you want is this..

addItem() {
document.querySelector("#textfield1").value = ""
this.setState({
            triggerAnimation: 'fadein',
            tasks: this.state.tasks.concat(this.state.inputText)}) 
}

You can use .concat method to create copy of your array with new data:

  addTask() {
    this.setState({tasks: this.state.tasks.concat(["new value"])})
  }

You also need to bind this to addTask in your constructor:

this.addTask = this.addTask.bind(this)

See my example:

https://jsfiddle.net/69z2wepo/103069/

Documentation: https://reactjs.org/docs/react-component.html#setstate

try this

import React from 'react';

class Todo extends React.Component {
  constructor(props) {
    super();
    this.state = {
      value: '',
      items: []
    }
  }

  onChange = e => this.setState({ value: e.target.value })

  onEnter = e => {
    if(e.charCode !== 13) return;
    this.addItem();
  };

  onClick = e => {
    this.addItem()
  };

  addItem = () => {
    const { value } = this.state;
    if(!!value.trim()) return;
    this.setState(prev => ({ items: [...prev.items, value], value: '' }))
  };

  render() {
    const { value } = this.state
    return (
      <div>
        <div>
          <input
            type="text"
            value={value}
            name="abc"
            onChange={this.onChange}
            onKeyPress={this.onEnter}
          />
        </div>
        <button onClick={this.onClick}>Add</button>
      </div>
    )
  }
}

FTFY better to just use comments in the code, regarding the problem(s) you want to get the tasks array then can concat the stuff to get a new array.

setState({tasks:this.state.tasks.concat([this.state.inputText])})

Wouldn't hurt to clean up the code some too... learning react myself the book "the road to learning react" has some good tips on how to set things up to be a bit more readable.


Edit actually put the right code here now...

With react, you're almost always going to have to store form field information in state (controlled components) so, how about turning todo task input field into a controlled component, like so:

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

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

        this.state = {
            inputText: '',
            triggerAnimation: '',
            tasks: []
        }

        this.onInputChange = this.onInputChange.bind(this);
        this.onInputKeyPress = this.onInputKeyPress.bind(this);
        this.addItem = this.addItem.bind(this);
    }

    onInputChange(e) {
        this.setState({ inputText: e.target.value });
    }

    onInputKeyPress(e) {
        if (e.key === "Enter") {
            this.addItem();
        }
    }

    addItem() {
        const itemToAdd = this.state.inputText;
        const tasks = this.state.tasks;
        this.setState({
            inputText: "",
            tasks: tasks.concat(itemToAdd);
        });
    }

    render() {
        const { inputText } = this.state;
        return(
            <div>
                <input type="text" className="inputclass" id="textfield1" placeholder='Enter a task.' 
                   value={inputText} onChange={this.onInputChange} onKeyPress={this.onInputKeyPress} />
                <br />
                <br />
                <button className="button" onClick={this.addItem} data-
                toggle='fadein' data-target='list'>+</button>
            </div>
        );
    }
}

Notice how input state is controlled via component state

发布评论

评论列表(0)

  1. 暂无评论