我正在开发一个小型购物清单应用程序。每当我提交表单时,我都会执行axios请求将项目添加到数据库并更新我的“items”状态以包含新的杂货项目。
问题是,除非我刷新页面,否则我的状态仍会显示一个空的“items”数组。 “items”数组的初始状态是从数据库中提取的,这可以通过使用componentDidMount并在其中设置“items”的状态来实现。
此外,在我的州,我有currentUser,它也从数据库中提取。如果我在添加第一个项目后尝试记录this.state.currentUser.shoppingList,它将显示一个空数组,即使我可以看到服务器端日志表明数组不为空。
这是我的代码:
**App Component**
import React from 'react';
import ListForm from './ListForm';
import * as helpers from '../helpers';
class App extends React.Component{
state = {
currentUser: {},
items: []
}
componentDidMount() {
console.log('Hello!');
helpers.fetchUser()
.then(data => {
this.setState({
currentUser: data,
items: data.shoppingList
}, () => {
console.log(this.state)
});
});
}
// Handle adding new items
onSubmit = (id, item) => {
this.setState({items: this.state.items.concat([item])});
helpers.addItem(id, item);
console.log(this.state);
}
// Handle deletion of items
onDelete = (id, deleteItem) => {
var shoppingList = this.state.currentUser.shoppingList;
var index = shoppingList.findIndex(x => x.name === deleteItem);
console.log(shoppingList);
helpers.removeItem(id, deleteItem);
}
render() {
return (
<div className="container row offset-4">
<div className="jumbotron col-sm-6">
<ListForm
currentUser={this.state.currentUser}
items={this.state.items}
onSubmit={this.onSubmit}
onDelete={this.onDelete}
/>
</div>
</div>
);
}
};
export default App;
Helpers.js
import axios from 'axios';
export const fetchUser = async () => {
const resp = await axios.get('/api/current_user');
return resp.data;
}
export const addItem = (id, newItem) => {
const resp = axios.post("/api/" + id + "/addItem", newItem);
return resp.data;
}
export const removeItem = (id, deleteItem) => {
const resp = axios.delete("/api/" + id + "/removeItem", {data: {item: deleteItem}});
return resp.data;
}
ListForm组件
import React from 'react';
import ListItem from './ListItem';
class ListForm extends React.Component {
state = {
value: ''
}
// Render content based on whether or not currentUser has been returned from
// our API request.
renderContent = () => {
const shoppingList = this.props.currentUser.shoppingList;
if(shoppingList === null || shoppingList === undefined) {
return (<h5>Loading List</h5>);
} else {
return (
<div>
{this.props.items.map((item, index) =>
<ListItem
{...item}
key={index}
id={index}
currentUser={this.props.currentUser}
onDelete={this.props.onDelete}
/>
)}
</div>
);
}
}
// Handle the submission of a new item to database and state.
handleSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.props.currentUser._id, {name: this.state.value});
this.setState(prevState => ({value: ''}));
}
// Handle any changes within the input.
onChange = e => {
this.setState({value: e.target.value});
}
render() {
return (
<div className="col-xs-9">
<h3>Grocery List</h3>
<form className="form-control" onSubmit={this.handleSubmit}>
<input style={{display: "inline", width: "60%", height: "2em"}} className="form-control" type="text"
value={this.state.value}
onChange={this.onChange}
/>
<button className="btn btn-success btn-sm float-right">Add item</button>
</form>
<div style={{marginTop: "10%"}}>
{this.renderContent()}
</div>
</div>
);
}
}
export default ListForm;
ListItem组件
import React from 'react';
const ListItem = props => {
// Handle delete item requests
const handleClick = event => {
var delItem = document.getElementById("btn" + props.id).textContent;
props.onDelete(props.currentUser._id, delItem);
}
return (
<div>
<li
style={{display: "inline"}} id={"btn" + props.id} key={props.id}>{props.name}
</li>
<button
style={{display: "inline"}} onClick={e => handleClick(e)} className="btn btn-danger btn-sm float-right">
Remove
</button>
<hr />
</div>
);
}
export default ListItem;
答案 0 :(得分:2)
与每次更改组件状态时调用的render()
不同,componentDidMount()
仅在组件被“挂载”之后,即在插入其DOM节点之后被调用一次在DOM中。有关“已装载”字词的详细信息,您可能需要查看Component Lifecyle Reference。
在您的代码中,添加项目会修改客户端的state.items
(顺便说一下,不是state.currentUser.shoppingList
),而fetchUser
函数只会被调用一次,因为它是{{{ 1}}客户端方法(参考:
https://reactjs.org/docs/react-component.html#componentdidmount)。
换句话说,当您使用componentDidMount
将项添加到数据库时,您的组件将不会与数据库更新同步,因为组件的状态未更新以反映后端中发生的更改。 / p>
如果您想将您的用户与数据库中的内容同步,那么您可以在将项目添加到数据库后调用addItem
,如下所示:
fetchUser
我没有测试代码,抱歉。也许更清洁的方式是“宣传” // Handle adding new items
onSubmit = (id, item) => {
this.setState({items: this.state.items.concat([item])});
helpers.addItem(id, item);
console.log(this.state);
helpers.fetchUser()
.then(data => {
this.setState({
currentUser: data,
items: data.shoppingList
}, () => {
console.log(this.state)
});
});
}
功能,就像你对addItem
所做的那样。
希望这有帮助!
答案 1 :(得分:1)
而不是:
onSubmit = (id, item) => {
this.setState({items: this.state.items.concat([item])});
helpers.addItem(id, item);
console.log(this.state);
}
试试这个:
onSubmit = (id, item) => {
this.setState({items: [...this.state.items,item]});
helpers.addItem(id, item);
console.log(this.state);
}