React函数组件EditProfile刷新后丢失状态无法预填表单问题
刷新页面后EditProfile组件无法预填用户数据的问题解决
我有一个EditProfile函数式组件,首次通过导航跳转加载时完全正常,但当用户在表单页面刷新后,组件丢失状态:表单不再用user状态预填输入框,变成空白,const [user, setUser] = useState({})中的user对象打印为空对象。
EditProfile组件代码
import React, { useEffect, useState } from 'react' import './EditProfile.css' export default function EditProfile(props) { const [user, setUser] = useState({}) let handleChange = (e) => { setUser({...user, [e.target.name]: e.target.value}) } let handleSubmit = async () => { let body = { _id: user._id, email: user.email, username: user.username, shortDescription: user.shortDescription, fullDescription: user.fullDescription, paymentInfo: user.paymentInfo, publisherAgreement: user.publisherAgreement } let options = { method: 'PUT', headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) } await fetch('/api/users/editProfile', options) .then(res => res.json()) .then(data => { this.props.setUserInState(data) }) } useEffect(() => { (async() => { setUser(props.user) })() },[]) console.log('here is the user: ' + JSON.stringify(user)) return ( <form className='editProfileForm' onSubmit={handleSubmit}> <input type='hidden' value={user._id}></input> <input type='hidden' value={user.email}></input> <div> <h4>Edit Profile</h4> <div className="form-group address-update"> <label className="inputUD"><span className="label"><b>Username</b></span></label> <input type="text" className="form-control" name="username" onChange={handleChange} value={user.username}></input> </div> <div className="form-group address-update"> <label className="inputUD"><span className="label"><b>Email</b></span></label> <input type="text" className="form-control" name="email" onChange={handleChange} value={user.email}></input> </div> {user.publisherAgreement && <div> <div className="form-group"> <label className="inputUD"><span className="label"><b>Short Description</b></span></label> <textarea type="text" className="form-control" name="shortDescription" onChange={handleChange} value={user.shortDescription}></textarea> </div> <div className="form-group"> <label className="inputUD"><span className="label"><b>Full Description</b></span></label> <textarea type="text" className="form-control" name="fullDescription" onChange={handleChange} value={user.fullDescription}></textarea> </div> <div className="form-group address-update"> <label className="inputUD"><span className="label"><b>Fake Payment Info</b></span></label> <input type="text" className="form-control" name="paymentInfo" onChange={handleChange} value={user.paymentInfo}></input> </div> </div> } <button type="submit" className="btn btn-success">Submit</button> </div> </form> ) }
调用该组件的App.jsx相关代码
state = { user: false, } setUserInState = (incomingUserData) => { console.log('incoming userdata: ' + JSON.stringify(incomingUserData)) this.setState({user: incomingUserData}) } componentDidMount() { let token = localStorage.getItem('token') if (token) { const payload = JSON.parse(atob(token.split('.')[1])) if (payload.exp < Date.now() / 1000) { localStorage.removeItem('token') token = null } else { this.setState({ user: payload.user }) } } } render() { return ( <div className="App"> <Navbar user={this.state.user} setUserInState={this.setUserInState}/> <Routes> <Route path='/ideas/create' element={<NewIdea user={this.state.user} setUserInState={this.setUserInState}/>}/> <Route path='/users/showProfile' element={<UserProfile user={this.state.user} setUserInState={this.setUserInState}/>}/> <Route path='/users/editProfile' element={<EditProfile user={this.state.user} setUserInState={this.setUserInState}/>}/> <Route path='/publishers/becomePublisher' element={<BecomePublisher user={this.state.user} setUserInState={this.setUserInState}/>} /> <Route path='/users/addSubscription'/> <Route path='/users/removeSubscription'/> <Route path='/publishers/show/:id' element={<PubProfile user={this.state.user}/>}/> <Route path='/ideas/show/:id' element={<PubIdeas user={this.state.user}/>}/> <Route path='/ideas/ideasFeed/:userId' element={<IdeasFeed user={this.state.user}/>}/> <Route path='/discover/:id' element={<Discover user={this.state.user} setUserInState={this.setUserInState}/>}/> <Route path='*' element={<Navigate to='/discover/:id' replace />}/> </Routes> </div> ) } }
页面通过Navbar组件的Link跳转访问,不刷新时表单正常,但刷新后无法预填数据。
解决方案
做两处修改即可解决问题:
- 更新useEffect的依赖数组
将useEffect的依赖数组添加props.user,这样当父组件App中的user状态更新(比如刷新后从localStorage读取token并设置user)时,useEffect会重新执行,将最新的props.user同步到组件内部的user状态:
useEffect(() => { (async() => { setUser(props.user) })() },[props.user])
- 修复函数组件中的
this引用错误
函数组件中不存在this,将fetch回调中的this.props.setUserInState(data)改为直接更新内部状态或调用props方法:
await fetch('/api/users/editProfile', options) .then(res => res.json()) .then(data => { setUser(data) // 也可以同步更新父组件状态:props.setUserInState(data) })
修改后,页面刷新后组件会自动从props同步最新的用户数据,表单能正常预填。
内容的提问来源于stack exchange,提问作者curtis
相关产品推荐
相关产品推荐

