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

React Router v6调用history.push仅URL变更未跳转页面问题排查

问题核心原因

  1. 你自行创建的customHistory和react-router v6中BrowserRouter内部维护的history实例不是同一个,你调用自定义history的push方法只能修改地址栏URL,无法触发Router内部的路由状态更新,所以页面不会重新渲染。
  2. Login组件的render函数中直接执行localStorage.removeItem('accessToken'),每次组件渲染都会清空token:你登录验证通过后异步存储token的操作完成后,组件会触发重渲染,刚存储的token会被立即清空,导致PrivateRoute鉴权失败,自然无法跳转到私有路由页面。

解决方案

步骤1:删除自定义history相关代码

修改routes.js,移除自定义history的创建和传参,同时实现适配类组件的withRouter高阶组件(v6官方移除了withRouter,可自行实现):

import React from 'react';
import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom'
import HomePage from './App/pages/HomePage'
import UsersPage from './App/pages/UsersPage'
import Login from './App/pages/Login'
import PrivateRoute from './Auth'

// 适配类组件的withRouter高阶组件
function withRouter(Component) {
  function ComponentWithRouterProp(props) {
    const navigate = useNavigate();
    return <Component {...props} navigate={navigate} />;
  }
  return ComponentWithRouterProp;
}

function RoutesController() {   
    return (
        <Router>
            <Routes>
                <Route path="/" element={<Login />} />
                <Route path="/home" element={<PrivateRoute />}>
                    <Route path="" element={<HomePage />} />
                </Route>
                <Route path="/users" element={<PrivateRoute />}>
                    <Route path="" element={<UsersPage />} />
                </Route>
                <Route path="*" element={<h1>NOT FOUND</h1>} />
            </Routes>
        </Router>
    )
}

export default RoutesController

步骤2:修改Login组件适配v6导航逻辑

  1. 导出Login时用上述withRouter包裹,获取navigate方法
  2. 将render中的token清空逻辑移到componentDidMount生命周期,避免每次渲染都删除token
  3. 登录成功后调用navigate方法跳转

修改后的Login.jsx核心代码:

import React, { Component } from "react";
import Wrapper from "../../../components/Wrapper";
import "./style.css"
import logo from "../../../assets/icons/logotipo_semfundo.png"
import Button from "@material-ui/core/Button";
import { MdEmail, MdLock } from "react-icons/md"
// 导入刚才实现的withRouter,或者单独抽离成公共文件引入
import { withRouter } from './routes'

class Login extends Component {
    constructor(props) {
        super(props)
        this.state = {
            message: '',
        }
    }       

    componentDidMount() {
      // 仅在组件首次挂载时清空token,不要放在render中
      localStorage.removeItem('accessToken')
    }

    signIn = () => {
        const data = { email: this.email, password: this.password }
        const requestInfo = {
            method: 'POST',
            body: JSON.stringify(data),
            headers: new Headers({
                'Content-Type': 'application/json'
            }),
        }

        fetch('http://localhost:3000/api/login', requestInfo).then(response => {
            if (response.ok) {
                return response.json()
            }
            throw new Error('Login Inválido...')
        }).then(token => {
            localStorage.setItem('accessToken', token)            
            // 用v6的navigate方法跳转
            this.props.navigate("/home", {state: {message: "Ok"}})
            return        
        }
        ).catch(e => (this.setState({ message: e.message })))
    }

    render() {
        return (
            <Wrapper className="login">
                <Wrapper className="login-img">
                    <img src={logo} alt="logo" />
                </Wrapper>

                <Wrapper className="login-form">
                    <h1 className="h1" >Login</h1>
                    {
                        this.state.message !== '' ? (
                            <span color="black">{this.state.message}</span>
                        ) : ''
                    }
                    <form id="loginForm">
                        <Wrapper>
                            <Wrapper>
                                <MdEmail />
                                <input
                                    id="email"
                                    type="text"
                                    name="email"
                                    placeholder="Digite um E-mail"
                                    onChange={e => this.email = e.target.value}
                                ></input>
                            </Wrapper>
                            <Wrapper>
                                <MdLock />
                                <input
                                    id="password"
                                    type="password"
                                    name="password"
                                    placeholder="Senha"
                                    onChange={e => this.password = e.target.value}
                                ></input>
                            </Wrapper>
                            <Wrapper>
                                <Button
                                    onClick={() => this.signIn()}
                                    color="primary"
                                >
                                    Entrar
                                </Button>
                            </Wrapper>
                        </Wrapper>
                    </form>
                </Wrapper>
            </Wrapper>
        )
    }
}

// 用withRouter包裹组件,注入navigate方法
export default withRouter(Login)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:54:00