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

React类组件路由刷新报错Cannot GET /exams/0的解决方法

解决React类组件路由刷新后「Cannot GET /exams/0」的问题

问题根源

这是单页应用(SPA)的经典路由问题:点击链接时,React Router在客户端完成路由跳转,不会向服务器发送请求;但刷新页面时,浏览器会直接向服务器请求/exams/0这个路径,而你的服务器没有配置对应路径的响应,因此返回404错误。

解决方案

方案1:改用HashRouter(无需服务器配置)

将路由模式切换为哈希模式,URL会带上#(例如/#/exams/0),刷新时浏览器只会请求根路径,React Router会解析#后的部分渲染对应页面。

修改路由配置:

// 替换BrowserRouter为HashRouter
import { HashRouter as Router, Routes, Route } from 'react-router-dom';

// 在根组件中用HashRouter包裹路由
class App extends Component {
  render() {
    return (
      <Router>
        {/* 你的现有路由结构 */}
      </Router>
    );
  }
}

方案2:配置服务器 fallback 到index.html(保持干净URL)

如果想要不带#的URL,需要配置服务器,让所有请求都返回React应用的index.html,由React Router接管路由处理。

开发环境(Create React App)

在package.json中添加:

"homepage": "."

重启开发服务器即可。

生产环境部署

  • Nginx配置:
    在nginx.conf的location块中添加:
    location / {
      try_files $uri $uri/ /index.html;
    }
    
  • Apache配置:
    在项目根目录创建.htaccess文件,添加:
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
    

补充:刷新后加载对应考试内容

解决路由问题后,还需要让DetailedExam组件根据URL中的id加载对应考试数据。由于类组件无法直接使用React Router的hooks,我们可以用高阶组件封装:

import { useParams } from 'react-router-dom';
import { dummyExams } from './FrontPage'; // 导入考试数据

// 高阶组件:给类组件传递路由参数
const withRouter = Component => {
  const Wrapper = props => {
    const params = useParams();
    return <Component {...props} params={params} />;
  };
  return Wrapper;
};

class DetailedExam extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hasStarted: false,
      exam: null
    };
    this.startExam = this.startExam.bind(this);
  }

  componentDidMount() {
    // 根据URL中的id获取对应考试
    const examId = parseInt(this.props.params.id);
    const targetExam = dummyExams[examId];
    this.setState({ exam: targetExam });
  }

  startExam() {
    this.setState(prevState => ({
      hasStarted: !prevState.hasStarted
    }));
  }

  render() {
    const { exam } = this.state;
    if (!exam) return <div>加载中...</div>;

    return (
      <div>
        <div>
          <h1>{exam.title}</h1>
          <p>{exam.content}</p>
          <div>
            <span>考试说明...</span>
          </div>
          <button onClick={this.startExam}>开始考试</button>
        </div>
      </div>
    );
  }
}

// 用高阶组件包裹组件,获取路由参数
export default withRouter(DetailedExam);

额外修复:FrontPage路由的element格式问题

你的FrontPage组件中,Route的element属性需要用Fragment包裹map返回的数组:

<Route
  path="/"
  element={
    <>
      {this.state.exams.map((exam, i) => {
        return (
          <FrontPageExam
            title={exam.title}
            text={exam.content}
            className={this.state.exams.length - i <= 2 ? "Last-Exam" : "Exam"}
            key={i}
            setIsExamOpen={this.setIsExamOpen}
            id={i}
          />
        );
      })}
    </>
  }
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:58:16