Also added a delete button but its not working, it says "Cannot read properties of undefined (reading 'deleteItem')" What am I doing wrong here?
<script type="text/babel">
"use strict";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
currentItem: {
text: "",
key: ""
}
};
this.handleInput = this.handleInput.bind(this);
this.addItem = this.addItem.bind(this);
this.deleteItem = this.deleteItem.bind(this);
this.setUpdate = this.setUpdate.bind(this);
}
handleInput(e) {
this.setState({
currentItem: {
text: e.target.value,
key: Date.now()
}
});
}
addItem(e) {
e.preventDefault();
const newItem = this.state.currentItem;
console.log(newItem);
if (newItem.text !== "") {
const newItems = [...this.state.items, newItem];
this.setState({
items: newItems, // <-- should be new items array built above
currentItem: {
text: "",
key: ""
}
});
}
}
deleteItem(key){
const filteredItems= this.state.items.filter(item =>
item.key!==key);
this.setState({
items: filteredItems
})
}
setUpdate(text, key) {
const items = this.state.items;
items.map(item => {
if(item.key===key) {
item.text=text;
}
})
this.setState({
items: items
})
}
render() {
return (
<div>
<form id="to-do-form" onSubmit={this.addItem}>
<input
type="text"
placeholder="Enter Text"
value={this.state.currentItem.text}
onChange={this.handleInput}
/>
<button type="submit">Add</button>
</form>
<ListItem items={this.state.items}
deleteItem = {this.deleteItem}
setUpdate = {this.setUpdate}/>
</div>
);
}
}
class ListItem extends React.Component {
render() {
return (
<div>
{this.props.items.map((item) => {
return (
<div className="list" key={item.key}>
<p><input type="text"
id={item.key}
value={item.text}
onChange ={
(e) => {
this.props.setUpdate(e.target.value, item.key)
}
}
/><button onClick={() => this.prop.deleteItem(item.key)}>Ta bort</button></p>
</div>
);
})}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
</script>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
This is the first time I'm coding i react and I am trying to add a new list item to the list in but I get "TypeError: e.render is not a function" in the console... I want to have all my code in the HTML file like I have right now. Can you see what I am doing wrong here? This is my code so far:
<div id="root"></div>
<script type="text/babel">
"use strict";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
currentItem: {
text:'',
key:''
}
}
this.handleInput = this.handleInput.bind(this);
this.addItem = this.addItem.bind(this);
}
handleInput(e) {
this.setState({
currentItem: {
text: e.target.value,
key: Date.now()
}
})
}
addItem(e) {
e.preventDefault();
const newItem = this.state.currentItem;
console.log(newItem);
if(newItem.text!=="") {
const items=[...this.state.items, newItem];
this.setState({
items: newItems,
currentItem: {
text:'',
key:''
}
})
}
}
render() {
return (
<div>
<form id="to-do-form" onSubmit={this.addItem}>
<input type="text" placeholder="Enter Text"
value={this.state.currentItem.text}
onChange={this.handleInput}/>
<button type="submit">Add</button>
</form>
<ListItem items = {this.state.items}></ListItem>
</div>
);
}
}
class ListItem extends React.Component {
constructor(props) {
super(props);
const items = props.items;
const ListItems = items.map(items => {
return <div className="list" key="item.key">
<p>{item.text}</p>
</div>
})
return (
<div>{ListItems}</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'))
</script>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You had a few misnamed variables. When adding items to this.state.items
you were referencing an undeclared newItems
variable when it should have been the items
variable declared locally.
Additionally, the ListItem
component was trying to save the passed props into a local class variable. Saving props locally is an anti-pattern in React, just render directly from the passed props values. ListItem
also was not providing a render
lifecycle method to return anything to render to the UI.
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<script type="text/babel">
"use strict";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
currentItem: {
text: "",
key: ""
}
};
this.handleInput = this.handleInput.bind(this);
this.addItem = this.addItem.bind(this);
}
handleInput(e) {
this.setState({
currentItem: {
text: e.target.value,
key: Date.now()
}
});
}
addItem(e) {
e.preventDefault();
const newItem = this.state.currentItem;
console.log(newItem);
if (newItem.text !== "") {
const newItems = [...this.state.items, newItem];
this.setState({
items: newItems, // <-- should be new items array built above
currentItem: {
text: "",
key: ""
}
});
}
}
render() {
return (
<div>
<form id="to-do-form" onSubmit={this.addItem}>
<input
type="text"
placeholder="Enter Text"
value={this.state.currentItem.text}
onChange={this.handleInput}
/>
<button type="submit">Add</button>
</form>
<ListItem items={this.state.items} />
</div>
);
}
}
class ListItem extends React.Component {
render() {
return (
<div>
{this.props.items.map((item) => {
return (
<div className="list" key={item.key}>
<p>{item.text}</p>
</div>
);
})}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
</script>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>