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.
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
]
});
}
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.