So I have a working "Todo" list implementation currently that's using Rails for a backend API and React for the frontend (Along with axios to make requests). Im familiar with Rails but React is still new to me.
Currently I have 4 Components, but the 2 I'm concerned with are List
and ListItem
.
List.js
import React, { Component } from 'react';
import axios from 'axios';
import ListItem from './ListItem';
class List extends Component {
constructor(props){
super(props)
this.state = {
listItems: [],
newItem: ''
}
}
componentDidMount() {
axios.get(`/api/v1/lists/${this.props.list.id}/list_items.json`)
.then(response => {
this.setState({
listItems: response.data
})
})
.catch(error => console.log(error))
}
addNewListItem = (list_id, content) => {
axios.post(`/api/v1/lists/${list_id}/list_items`, {
content: content
})
.then(response => {
const listItems = [ ...this.state.listItems, response.data ]
this.setState({
listItems: listItems,
newItem: ''
})
})
.catch(error => {
console.log(error)
})
}
removeListItem = (listItem_id) => {
axios.delete(`/api/v1/list_items/${listItem_id}`)
.then(response => {
const listItems = this.state.listItems.filter(
listItem => listItem.id !== listItem_id
)
this.setState({listItems})
})
.catch(error => {
console.log(error)
})
}
handleChange = (e) => {
this.setState({ newItem: e.target.value });
}
render() {
return (
<div key={this.props.list.id}>
<div className="card">
<div className="card-body">
<h4 className="card-title">{this.props.list.title}</h4>
<p className="card-text">{this.props.list.description}</p>
</div>
<ul className="list-group list-group-flush">
{this.state.listItems.map( listItem => {
return <li className="list-group-item" key={listItem.id}><ListItem listItem={listItem} removeListItem={this.removeListItem}/></li>
})}
</ul>
</div>
<form>
<div className="form-group">
<input className="form-control" placeholder="...." value={this.state.newItem} onChange={this.handleChange}/>
</div>
<button className="btn btn-primary btn-sm mx-1" onClick={() => this.addNewListItem(this.props.list.id, this.state.newItem)}>Add Item</button>
<button className="btn btn-info btn-sm mx-1" onClick={() => this.props.onUpdateList(this.props.list.id)}>Update</button>
<button className="btn btn-danger btn-sm mx-1" onClick={() => this.props.onRemoveList(this.props.list.id)}>Erase</button>
</form>
</div>
)
}
}
export default List;
ListItem.js
import React, { Component } from 'react';
const ListItem = (props) =>
<div className="list-item" >
{props.listItem.content}
<button className="float-right btn btn-outline-danger btn-sm" onClick={() => props.removeListItem(props.listItem.id)}>Delete</button>
</div>
export default ListItem;
ListContainer
wraps around List
however that's not the issue im facing. It seems that when I add an item to my List, it causes a refresh of the entire page (I can see the styling go away for a second). I tried to take a sample video but unfortunately the video doesn't show it since it happens so quickly.
I can tell the screen is refreshing because when I watch the console and "preserve log" I see this:
VM412:1 XHR finished loading: POST "http://localhost:3000/api/v1/lists/8/list_items".
then
Navigated to http://localhost:3000/?
So it seems like after I POST to my API (and update the state) what I feel like is happening is that it's re-rendering on the addNewListItem
AND on the componentDidMount
. Maybe im mis-using componentDidMount
but it made the most sense to pull in the "most updated" items when the component mounts.
It's odd that it's getting re-called though? Shouldn't componentDidMount
only get called once? (I can tell in my console it's getting called again after the AddNewListItem
runs based on console logs. Or maybe it's working fine and this is just some weird browser glitch from running locally?