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

React(v18.2.0)应用点击浏览器返回按钮页面不刷新的问题求助

问题:React Router v5点击浏览器返回按钮URL变化但页面不更新

我有一个基于React(v18.2.0)和react-router-dom(v5.2.0)的应用,导航功能正常,但点击浏览器返回按钮时,URL发生变化,但页面状态未更新、也未重新渲染。例如,从ListUserComponent跳转到CreateUserComponent后,点击返回按钮,URL变回列表页路径,但页面仍停留在创建用户页面。


App.js

import React from 'react';
import './App.css';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import ListUserComponent from './components/ListUserComponent';
import HeaderComponent from './components/HeaderComponent';
import FooterComponent from './components/FooterComponent';
import CreateUserComponent from './components/CreateUserComponent';
import UpdateUserComponent from './components/UpdateUserComponent';
import ViewUserComponent from './components/ViewUserComponent';

function App() {
  return (
    <div>
      <Router forceRefresh={true}>
          <HeaderComponent />
            <div className="container">
              <Switch>
                <Route path = "/" exact component = {ListUserComponent}></Route>
                <Route path = "/users" component = {ListUserComponent}></Route>
                <Route path = "/add-user/:id" component = {CreateUserComponent}></Route>
                <Route path = "/view-user/:id" component = {ViewUserComponent}></Route>
              </Switch>
            </div>  
          <FooterComponent />
      </Router>
    </div>
  );
}

export default App;

CreateUserComponent.jsx

import React, { Component } from 'react';
import UserService from '../services/UserService';

class CreateUserComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
            //Step 2
            id: this.props.match.params.id,
            firstName: '',
            lastName: '',
            email: '',
            password: ''
        }

        this.changeFirstNameHandler = this.changeFirstNameHandler.bind(this);
        this.changeLastNameHandler = this.changeLastNameHandler.bind(this);
        this.saveOrUpdateUser = this.saveOrUpdateUser.bind(this);
    }

    //Step 3        
    componentDidMount() {
        //Step 4
        if (this.state.id === 'add') {
            return
        } else {
            UserService.getUserById(this.state.id).then((res) => {
                let user = res.data;
                this.setState({
                    firstName: user.firstName,
                    lastName: user.lastName,
                    emailId: user.emailId
                });
            });
        }
    }

    saveOrUpdateUser = (e) => {
        e.preventDefault();
        let user = { firstName: this.state.firstName, lastName: this.state.lastName, email: this.state.email, password: this.state.password };
        console.log('user => ' + JSON.stringify(user));

        //Step 5
        if (this.state.id === 'add') {
            UserService.createUser(user).then(res => {
                this.props.history.push('/users');
            });
        } else {
            UserService.updateUser(user, this.state.id).then(res => {
                this.props.history.push('/users');
            });
        }
    }

    changeFirstNameHandler = (event) => {
        this.setState({ firstName: event.target.value });
    }

    changeLastNameHandler = (event) => {
        this.setState({ lastName: event.target.value });
    }

    changeEmailHandler = (event) => {
        this.setState({ email: event.target.value });
    }

    changePasswordHandler = (event) => {
        this.setState({ password: event.target.value });
    }

    cancel() {
        this.props.history.push('/users');
    }

    getTitle() {
        if (this.state.id === 'add') {
            return <h3 className="text-center">Modificar Usuario</h3>
        } else {
            return <h3 className="text-center">Añadir Usuario</h3>
        }
    }


    render() {
        return (
            <div>
                <div className="container">
                    <div className="row">
                        <div className="card col-md-6 offset-md-3 offset-md-3">
                            {
                                this.getTitle()
                            }
                            <div className="card-body">
                                <form>
                                    <div className="form-group">
                                        <label>Nombre: </label>
                                        <input placeholder="Nombre" name="firstName" className="form-control" value={this.state.firstName} onChange={this.changeFirstNameHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Apellidos: </label>
                                        <input placeholder="Apellidos" name="lastName" className="form-control" value={this.state.lastName} onChange={this.changeLastNameHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Email: </label>
                                        <input placeholder="Email" name="email" className="form-control" value={this.state.email} onChange={this.changeEmailHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Contraseña: </label>
                                        <input placeholder="Contraseña" name="password" className="form-control" value={this.state.password} onChange={this.changePasswordHandler} />
                                    </div>
                                    <button className="btn btn-success" onClick={this.saveOrUpdateUser}>Guardar</button>
                                    <button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{ marginLeft: "10px" }}>Cancelar</button>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default CreateUserComponent;

package.json

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.1.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

解决方案

1. 移除forceRefresh={true}

Router组件中的forceRefresh={true}会强制页面整页刷新,在React 18与React Router v5的组合下易导致路由状态异常,直接移除该属性:

<Router>
  {/* 其余代码保持不变 */}
</Router>

2. 给类组件添加路由变化监听

对于ListUserComponent这类类组件,需要监听路由location变化来触发数据重新获取和组件重渲染。通过withRouter高阶组件包裹组件,并使用componentDidUpdate生命周期:

import { withRouter } from 'react-router-dom';
import UserService from '../services/UserService';

class ListUserComponent extends Component {
  componentDidMount() {
    this.fetchUsers();
  }

  componentDidUpdate(prevProps) {
    // 路由location变化时重新拉取数据
    if (this.props.location !== prevProps.location) {
      this.fetchUsers();
    }
  }

  fetchUsers = () => {
    UserService.getUsers().then(res => {
      this.setState({ users: res.data });
    });
  }

  // 其余组件代码...
}

// 用withRouter包裹以获取location属性
export default withRouter(ListUserComponent);

3. 升级react-router-dom到v5最新版本

React 18与react-router-dom v5.2.0存在兼容性隐患,升级到v5系列最新版本可解决部分异常:

npm install react-router-dom@5.3.4

4. 全局监听路由变化(可选)

若上述方法无效,可在App组件中添加全局路由监听,确保页面状态同步:

import { useEffect } from 'react';
import { useHistory } from 'react-router-dom';

function App() {
  const history = useHistory();

  useEffect(() => {
    const unlisten = history.listen(() => {
      // 路由变化时可执行全局状态更新逻辑,比如强制刷新列表
    });
    return () => unlisten();
  }, [history]);

  // 其余组件代码...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:55:20