Im writing a "Todo" app to learn React, and this is my first app (it's using Rails as a backend). Currently I have two components that handle state, which is where im running into an issue.
ListContainer holds the state for "Lists", and a "List" holds the state for individual ListItems. Right now Lists work just fine, however I want to add a simple input box for my "List" component that can quickly add a new ListItem to the List. Currently im able to add a "test" value just fine.
One way would be to make a ListItemForm component, but that seems so unnecessary to just send one value. Im more of a backend person so im sure there is an easy way that's just not obvious. My javascript is also pretty rusty, so im sure it's riddled with errors.
Anyways here is the List component:
import React, { Component } from 'react';
import axios from 'axios';
import ListItem from './ListItem';
class List extends Component {
constructor(props){
super(props)
this.state = {
listItems: []
}
}
componentDidMount() {
axios.get(`/api/v1/lists/${this.props.list.id}/list_items.json`)
.then(response => {
console.log("Getting List 'listitems'")
console.log(response.data)
console.log(this.state.listItems)
this.setState({
listItems: response.data
})
console.log(this.state)
})
.catch(error => console.log(error))
}
addNewListItem = (list_id, content) => {
axios.post(`/api/v1/lists/${list_id}/list_items`, {
content: content
})
.then(response => {
console.log(response)
const listItems = [ ...this.state.listItems, response.data ]
this.setState({listItems})
console.log("state of list")
console.log(this.state)
})
.catch(error => {
console.log(error)
})
}
removeListItem = (listItem_id) => {
console.log("listItem_id :" + listItem_id);
axios.delete(`/api/v1/list_items/${listItem_id}`)
.then(response => {
console.log(response);
const listItems = this.state.listItems.filter(
listItem => listItem.id !== listItem_id
)
this.setState({listItems})
})
.catch(error => {
console.log(error)
})
}
render() {
return (
<div className="single-list" key={this.props.list.id}>
<h4>{this.props.list.title}</h4>
<p>{this.props.list.description}</p>
{console.log(this.props.list)}
{this.state.listItems.map( listItem => {
return <ListItem key={listItem.id} listItem={listItem} removeListItem={this.removeListItem}/>
})}
<button onClick={() => this.props.onRemoveList(this.props.list.id)}>Erase</button>
<button onClick={() => this.props.onUpdateList(this.props.list.id)}>Update</button>
<button onClick={() => this.addNewListItem(this.props.list.id,"test")}>Add</button>
</div>
)
}
}
export default List;
I would like the field to be at the bottom and just be a text field with a button. Or is it as simple as having an input and attaching a submit button and onClick handler to send e.target.value to the addNewListItem function? Or am I overthinking this?
Hopefully it makes sense to have the input form within the "List" component and not "ListItem"
<input>, attaching aonInputto it.onInputwill fire everytime the text changes?<form>. If you want things to happen "on a button press", add your event listener to that button. But it's also important to remember how React works when it comes to capturing user input: you're still going to need to haveonChangehandling on that input to actually get the value the user's typing, and storing that in your state. Then your button's onClick can do whatever it needs to do with that state value; it should not try to access the input element's DOM node or something.