简体   繁体   中英

Why is my element not being appended to my array state?

I am trying to build a simple todo app using React, which contains a text input area for the user, and an "ADD" button that when clicked, adds the user's text input to an ordered list underneath. Below is a part of my entire code that I believe pertains to this issue:

import React from "react";
import TextBar from "./TextBar";
import AddButton from "./AddButton";
import ListEntry from "./ListEntry";

class UserToDoInput extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      userTextInput: "",
      listArray: ["test1", "test2", "test3"]
    };
    this.updateText = this.updateText.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({
      listArray: [...this.listArray, this.userTextInput]
    });
  }

  updateText(evt) {
    this.setState({
      userTextInput: evt.target.value
    });
  }

  render() {
    return (
      <div>
        <form className="form-inline" id="usertodoinput">
          <TextBar function={this.updateText} compValue={this.state.userTextInput} />
          <AddButton function={this.handleClick} />
        </form>
        <ListEntry compValue={this.state.listArray} />
      </div>
    );
  }
}

export default UserToDoInput;

As you can see in the code above, the handleClick function is triggered when the "ADD" button is clicked by the user, thus, resulting in the user's text input in the TextBar component, to be appended to the listArray state. This listArray array would then be mapped inside the ListEntry component into an ordered list.

Theworks as it does map the listArray into an ordered list. I know this as I have three "tester" elements in the listArray array, that is, test1, test2, test3 . And all of these "tester" elements are visibly converted to an ordered list.

However, when I view my listArray array after manually inputting a value into the text input and clicking the "ADD" button, I can see in my Chrome Extension for React that my listArray is not updated with the new appended value.

When I view my handleClick function, there does not seem to be any syntax errors, so what could be the reason for this error?

Thanks for the help

UPDATE

As suggested by one of the answerers, Prateek Thapa, below is my code for the TextBar, AddButton, ListEntry components, respectively.

TextBar component:

import React from "react";

class TextBar extends React.Component {
  render() {
    return (
      <input type="text" className="form-control" id="textbar" placeholder="What I should get done today..." onChange={this.props.function} value={this.props.compValue} />
    );
  }
}

export default TextBar;

AddButton component:

import React from "react";

class AddButton extends React.Component {
  render() {
    return (
      <button className="btn btn-primary mb-2" id="addbutton" onClick={this.props.function}>ADD</button>
    );
  }
}

export default AddButton;

ListEntry component:

import React from "react";

class ListEntry extends React.Component {

  render() {
    return (
      <div>
        <ol>
          {this.props.compValue.map((elem, i) => <li key = {i}>{elem}</li>)}
        </ol>
      </div>
    );
  }
}

export default ListEntry;

Fix your typo from this.listArray to this.state.listArray

 handleClick() {
    this.setState({
      listArray: [...this.state.listArray, this.state.userTextInput]
    });
  }

You could also use the updater version. In this case, this.setState takes a function which gets the prevState as the parameter.

handleClick() {
    this.setState((prevState) => ({
      listArray: [...prevState.listArray, this.state.userTextInput]
    }));
  }

you have missed using state in setState

handleClick() {
    this.setState({
      listArray: [...this.state.listArray, this.state.userTextInput]
    });
  }

The problem here is that the input field and button is within a form tag and the default behaviour from browsers is to interpret a button within a form as a <input type="submit"/> thus refreshing the page and all state is lost and the component is rerendered.

  handleClick(evt) {
    evt.preventDefault() // this line prevents the refresh from happening. 
    this.setState({
      listArray: [...this.listArray, this.userTextInput]
    });
  }

Another solution is just not to use the form element. It doesn't really serve a true purpose for things like this one.

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