简体   繁体   中英

Display new list item onclick with ReactJS

I have a problem with updating and displaying an array as list items on the click of a button. From below code, I get error message:

list.map is not a function

import React from "react";


export default class InputPushToList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      ActiveText: "",
      li: ["First Item"]
    };

    this.handleOnClick = this.handleOnClick.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.setState({
      ActiveText: e.target.value
    });
  }

  handleOnClick(e) {
    e.preventDefault();

    const newListItem = [this.state.ActiveText];

    this.setState({
      li: this.state.li.push(newListItem)
    });
  }

  render() {
    const list = this.state.li;
    return (
      <React.Fragment>
        <h2>{this.props.inputTitle}</h2>
        <input type="text" onChange={this.handleChange} />
        <h2>{this.state.ActiveText}</h2>
        <br />
        <button onClick={this.handleOnClick}>Add to list</button>

        <ul>
          {list.map(e => (
            <li>{e}</li>
          ))}
        </ul>
      </React.Fragment>
    );
  }
}

In my mind list.map is a function but apparently not, so why? And how would you go about displaying one more (that which is the active state of the input, this.state.ActiveText) list item when clicking the button? Thanks for the help.

First thing first, you don't use this.state inside this.setState, instead use a function to update state. Check this for reference: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

Your code should be as follows:

this.setState((state) => ({
  li: state.li.concat([newListItem])
}));

Second, why are you assigning an array to newlistitem by doing: const newListItem = [this.state.ActiveText]; ?

It should be const newListItem = this.state.ActiveText;

Problem is this line:

this.setState({
      li: this.state.li.push(newListItem)
    });

example:

var arr = [];
console.log(arr.push({}))// it will print 1.

in your case:

this.setState({
      li: this.state.li.push(newListItem)// here you assigned `li`1.
    });

Fix the above.

1. Don't mutate this.state

In handleOnClick() , do not write this.state.li.push(newListItem) .

Instead, make a clone of this.state.li , add newListItem into that clone, and set the state of li to the new clone:

handleOnClick(e) {
  e.preventDefault();
  this.setState({
    li: [
      ...this.state.li, // spread out the existing li
      this.state.ActiveText // append this newListItem at the end of this array
    ]
  });
}

2. Consider destructuring

In your render() , you could destructure this.state.li :

render() {
  const { li } = this.state
  return (
    <React.Fragment>
      ...other stuffs
      <ul>
        {li.map(e => (
          <li>{e}</li>
        ))}
      </ul>
    </React.Fragment>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM