Reputation: 91
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.
Upvotes: 0
Views: 6416
Reputation: 10944
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;
Upvotes: 1
Reputation: 3451
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>
);
}
Upvotes: 1
Reputation: 12103
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.
Upvotes: 1