因此,我目前有一个有效的“ Todo”列表实现,该实现使用Rails用作后端API,而React使用前端(随axios发出请求)。我对Rails很熟悉,但是React对我来说仍然是新手。
目前我有4个组件,但我关心的2个组件是List
和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
环绕List
,但这不是我要面对的问题。看来,当我向列表中添加一个项目时,它会刷新整个页面(我可以看到样式消失了一秒钟)。我试图拍摄一个示例视频,但不幸的是,由于发生得太快,该视频没有显示。
我可以告诉屏幕正在刷新,因为当我观看控制台并“保留日志”时,我看到了:
VM412:1 XHR完成加载:POST “ http://localhost:3000/api/v1/lists/8/list_items”。
然后
是否已导航到http://localhost:3000/?
因此,似乎在我发布到我的API(并更新状态)之后,我感觉正在发生的事情是它在addNewListItem
和componentDidMount
上重新呈现。也许我误用了componentDidMount
,但是在组件安装时插入“最新”项是最有意义的。
奇怪的是它被重新调用了吗? componentDidMount
不应该只被打一次电话吗? (我可以在控制台中根据控制台日志告诉AddNewListItem
运行之后再次被调用。或者也许运行正常,这只是本地运行时出现的一些奇怪的浏览器故障?
答案 0 :(得分:1)
当您将按钮放置在表单中而不指定类型时,它们将默认为submit
,从而导致您在尝试调用form
操作时重新加载页面。养成始终指定按钮类型-<button type="button">
的习惯。
对于实际提交表单的按钮,将类型设置为submit
并使用<form onSubmit={handleSubmit}>
处理事件,并记住在其中调用event.preventDefault()
以停止页面重新加载。您不应该使用onClick
处理提交按钮,这是一种不好的做法,因为它不可访问(返回键不会提交表单)。但是onClick
对于不提交动作是可以的。
您还应该将ListItem
包装在备忘录中,因为即使更改了一项,当前每一项仍在重新对帐-export default React.memo(ListItem)
在功能上等同于React.PureComponent
。