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

React应用导航返回后刷新丢失Redux状态,请求技术支援

React礼品店应用状态丢失问题

问题现象

用户登录后主页正常显示Welcome {username},但进入产品详情页后点击浏览器返回按钮回到主页时,应用触发整页刷新,导致Redux中存储的用户状态全部丢失,需重新登录。

相关代码

App.js

import './App.css';
import Main from './components/main/main';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './store';
import Items from './components/items/items';
import ProductInfo from './components/productInfo/productInfo';
import UserInterface from './components/userInterface/userInterface';
import Profile from './components/profile/profile';

function App() {
  return (
    <Provider store={store}>
      <Router className="App">
        <Routes>
          <Route exact path='/' element={
            <div id='Homepage'>
              <Profile />
              <Main />
              <Items/>
            </div>
          }></Route>
          <Route exact path='/product-info/:id' element={<ProductInfo/>}></Route>
          <Route exact path='/user-form' element={<UserInterface/>}></Route>
        </Routes>
      </Router>
    </Provider>
  );
}

export default App;

Profile.js(负责接收和展示用户数据)

import React, { Component } from 'react'
import './profile.css';
import { connect } from 'react-redux';
import { checkUser } from '../../actions/userActions';

class Profile extends Component {
    state = {
        user : {
            isLoggedIn : false,
            userName : '',
            email : '',
            password : ''
        }
    }

    componentDidMount(){
        this.props.checkUser()
        const currentUser = this.props.user.user;
        console.log(currentUser);
        this.setState({
            user : currentUser
        })
    }
    
    render() {
        const {user} = this.state;
        return (
          <div>
            {user?.isLoggedIn ? <h2 id='welcome-user'>Welcome {user.userName}</h2> : 
                <a id="profile-area" href='/user-form'>
                    <img src="user.png" alt="profile" id="profile-img" />
                </a>
            }
          </div>
        )
      }
}

const mapUserStateToProps = (state) => {
    return{
        user : state?.myUser
    }
}

export default connect(mapUserStateToProps, {checkUser})(Profile);

UserInterface.js(登录表单,将输入提交至Redux状态)

import React from 'react'
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router';
import { getUser } from '../../actions/userActions';
import { connect } from 'react-redux';

import './userInterface.css';

function UserInterface(props) {
  const [userInfo, setUserInfo] = useState({
    isLoggedIn : false,
    userName : '',
    email : '',
    password : ''
  })

  const navigate = useNavigate();
  let alertMsg =  '';

  const getInputToState = (e,inputField) => {
    switch(inputField){
      case 'username' : {
        setUserInfo(userInfo.userName = e.target.value);
        const newUserInfo = userInfo;
        setUserInfo(newUserInfo);
        console.log(userInfo);
        break
      }
      case 'email' : {
        setUserInfo(userInfo.email = e.target.value);
        const newUserInfo = userInfo;
        setUserInfo(newUserInfo);
        console.log(userInfo);
        break
      }
      case 'password' : {
        setUserInfo(userInfo.password = e.target.value) ;
        const newUserInfo = userInfo;
        setUserInfo(newUserInfo);
        console.log(userInfo);
        break
      }
      default:
        return null
      }
  }
  
  const onSubmit = (e) => {
    e.preventDefault();
    let namePattern = /[A-Za-z0-9]{3,16}./ ;
    let emailPattern = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;

    if(userInfo.userName?.match(namePattern) && userInfo.email?.match(emailPattern) && userInfo.password.length >= 8){
      setUserInfo(userInfo.isLoggedIn = true);
      props.getUser(userInfo);
      navigate("/");
    }else{
      document.querySelector('#alert-msg').innerText = 'username, email or password are invalid';
    }
  }
  
  return (
    <div id='user-div'>
        <form id='user-form'>
            <h2 id="form-title">Tell us who you are :)</h2>
            <ul id="form-inputs">
              <li className="form-input">
                <input type="text" className="user-input" placeholder='Enter a username' maxLength={16} onChange={(e) => getInputToState(e, "username")}/>          
              </li>
              <li className="form-input">
                <input type="text" className="user-input" placeholder='Enter your e-mail' onChange={(e) => getInputToState(e, "email")}/>
              </li>
              <li className="form-input">
                <input type="text" className="user-input" placeholder='Create a password' onChange={(e) => getInputToState(e, "password")}/>
              </li>
              <li className="form-input">
                <a><button className='action-form' id='submit-button' onClick={onSubmit}>Submit</button></a>
              </li>
            </ul>
            <h4 id='alert-msg' ></h4>
            <h3 id='login-sign'>Already have an account ? <a href="/" id='login-form'>Log In</a></h3>
        </form>
    </div>
  )
}

const mapStateToProps = (state) => {
  return {
    myUser : state?.usersReducer
  }
}

export default connect(mapStateToProps, {getUser})(UserInterface) ;

UserReducer.js

const initialState = {
    user : {
        isLoggedIn : false,
        userName : '',
        email : '',
        password : ''
    }
};

export default function(state = initialState, action){
    switch(action.type){
        case 'GET_USER':
            initialState.user = action.payload;
        case 'CHECK_USER':
            return{
                ...state
            }
        default: 
            return state
    }
}

问题分析与修复方案

核心问题点

  1. 原生<a>标签触发整页刷新:Profile和UserInterface组件中使用原生<a href>跳转,会强制浏览器刷新页面,清空内存中的Redux状态。
  2. Reducer违反不可变更新原则:直接修改initialState且缺少break语句,导致状态更新不被Redux正确检测。
  3. Profile组件未同步Redux状态变化:仅在挂载时获取一次状态,后续Redux状态更新无法同步到组件视图。

修复步骤

1. 替换原生跳转为React Router客户端导航

将所有原生<a>标签替换为React Router的Link组件,避免整页刷新:

  • Profile.js:导入Link并替换跳转标签
import { Link } from 'react-router-dom';

// 替换render中的a标签
{user?.isLoggedIn ? <h2 id='welcome-user'>Welcome {user.userName}</h2> : 
    <Link id="profile-area" to='/user-form'>
        <img src="user.png" alt="profile" id="profile-img" />
    </Link>
}
  • UserInterface.js:同样替换登录跳转的a标签
import { Link } from 'react-router-dom';

// 替换对应代码
<h3 id='login-sign'>Already have an account ? <Link to="/" id='login-form'>Log In</Link></h3>

2. 修复Reducer的状态更新逻辑

遵循Redux不可变原则,正确返回新状态并添加break:

const initialState = {
    user: {
        isLoggedIn: false,
        userName: '',
        email: '',
        password: ''
    }
};

export default function(state = initialState, action) {
    switch(action.type) {
        case 'GET_USER':
            return {
                ...state,
                user: action.payload
            };
        case 'CHECK_USER':
            return {
                ...state
            };
        default: 
            return state;
    }
}

3. 让Profile组件实时同步Redux状态

移除组件自身的user状态,直接使用Redux映射的props,确保视图随状态更新:

import React, { Component } from 'react'
import './profile.css';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { checkUser } from '../../actions/userActions';

class Profile extends Component {
    componentDidMount() {
        this.props.checkUser();
    }
    
    render() {
        const { user } = this.props.user;
        return (
            <div>
                {user?.isLoggedIn ? <h2 id='welcome-user'>Welcome {user.userName}</h2> : 
                    <Link id="profile-area" to='/user-form'>
                        <img src="user.png" alt="profile" id="profile-img" />
                    </Link>
                }
            </div>
        )
    }
}

const mapUserStateToProps = (state) => {
    return {
        user: state?.myUser
    }
}

export default connect(mapUserStateToProps, { checkUser })(Profile);

4. 可选:持久化Redux状态(防止意外刷新丢失)

若希望页面刷新后仍保留用户状态,可使用redux-persist将状态存储到localStorage:

  • 安装依赖:npm install redux-persist
  • 修改store配置,添加持久化逻辑
  • 在App.js中用PersistGate包裹路由组件

内容的提问来源于stack exchange,提问作者islam gueniari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:15:48