反应应用程序的状态是不是最新的,我在我的数据库中?
我正在制作一个小杂货清单应用程序。 每当我提交一个表单,我执行一个axios请求将项目添加到数据库,并更新我的“项目”状态,以包含新的杂货项目。
问题是,除非我刷新页面,我的状态仍然显示一个空的“项目”数组。 “items”数组的初始状态是从数据库中提取出来的,通过使用componentDidMount并在那里设置“items”的状态。
另外,在我的状态,我有当前的用户也从数据库中拉出。 如果在添加我的第一个项目之后尝试loginthis.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;
与每次组件状态改变时调用的render()
不同, componentDidMount()
在组件被“挂载”之后,也就是在DOM节点被插入到DOM之后,只调用一次。 有关“已安装”术语的更多详细信息,可能需要查看“ 组件生命周期参考” 。
在你的代码中,添加一个项目将会修改你的客户端的state.items
(顺便说一句,不是state.currentUser.shoppingList
),你的fetchUser
函数作为componentDidMount
客户端方法的一部分被调用(参考: https:// reactjs .org / docs / react-component.html#componentdidmount )。
换句话说,当使用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) }); }); }
虽然我没有testing代码,对不起。 也许一个更清晰的方法是“promisify”你的addItem
函数就像你为fetchUser
做的。
希望这可以帮助!
而不是这个:
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); }