You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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跳转访问,不刷新时表单正常,但刷新后无法预填数据。


解决方案

做两处修改即可解决问题:

  1. 更新useEffect的依赖数组
    将useEffect的依赖数组添加props.user,这样当父组件App中的user状态更新(比如刷新后从localStorage读取token并设置user)时,useEffect会重新执行,将最新的props.user同步到组件内部的user状态:
useEffect(() => {
    (async() => {
        setUser(props.user)
    })()
},[props.user])
  1. 修复函数组件中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 17:20:35