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

React作品集网站部署后Contact Form刷新出现404 NotFound问题

React SPA部署后刷新非根路径出现404问题解决

问题描述

开发React作品集网站,本地运行正常,部署到线上服务器后出现异常:提交Contact Form并刷新页面时,浏览器控制台提示GET 404 - NOT FOUND,URL保持不变但无法访问,且该路径已在React Router中配置,当前使用emailjs实现表单发送功能。

相关代码

ContactForm组件

import React from 'react';
import { useRef } from 'react';
import './contactForm.css';
import { Footer } from '../../containers';

import emailjs from '@emailjs/browser';

const ContactForm = () => {
     const form = useRef();

     const sendEmail = (e) => {
       e.preventDefault();
   
       emailjs.sendForm('service_ebesa9d', 
                        'template_846mobc', 
                        form.current, 
                        '1oviDjIxcKzRsgPPd')

         .then((result) => {
             console.log(result.text);
             console.log("message sent");
             alert("Message sent succesfully");
            //  window.location.reload(false);
         }, (error) => {
             console.log(error.text);
             alert("Oops, something went wrong");
         });
     };

  return (
    <div className='RO__ContactForm' id='contactForm'>
        <div className='RO__ContactForm-title'>
            <h3>Contact</h3>
            <h1>I'm here to help you level up</h1>
        </div>
        <div className='RO__ContactForm-content'>
            <div className='RO__ContactForm-content_description'>
                <p>I'm just on click away to help you take your company 
                    to the next level. Fill in the form to share more 
                    details about the project or your favorite movie. 
                    Either way, I'd love to talk.</p>
            </div>
            <form
                className='RO__ContactForm-content_form'
                ref={form}
                onSubmit={sendEmail}
                >
                <div className='RO__ContactForm-content_form_name'>
                    <div className='RO__ContactForm-content_form_nameTitle'>
                        <h5>What's your name?</h5>
                    </div>
                    <input 
                        className='RO_ContactForm-content_form_nameInput'
                        type= 'text'
                        id='user_name'
                        name='user_name' required 
                    />
                </div>
                <div className='RO__ContactForm-content_form_email'>
                    <div className='RO__ContactForm-content_form_emailTitle'>
                        <h5>Your email</h5>
                    </div>
                    <input
                        className='RO__ContactForm-content_form_emailInput'
                        type='email'
                        id='user_email'
                        name='user_email' required
                    />
                </div>
                <div className='RO__ContactForm-content_form_info'>
                    <div className='RO__ContactForm-content_form_infoTitle'>
                        <h5>What can I help you with?</h5>
                    </div>
                    <textarea
                        className='RO__ContactForm-content_form_infoContent'
                        id='message'
                        name='message' required
                    />
                </div>
                <div className='RO__ContactForm-content_form_button'>
                    <button 
                        type='submit'
                        value='send'
                    >
                        Submit
                    </button>
                </div>
            </form>
        </div>
        <div className='RO__ContactForm-footer'>
            <Footer  />
        </div>
    </div>
  );
}

export default ContactForm

路由配置

import React from 'react';
import { Routes, Route } from 'react-router-dom';

import { Footer, About, Features, Services, Header, Portfolio, Contact } from './containers';
import { Article, Brand, Cta, Feature, Navbar, ScrollToTop } from './components';
import { Project1, Project2, Project3, Project4, Project5, Project6, Project7 } from './pages'
import { ContactForm } from './pages/contactform';

import './App.css';

const App = () => {
  return (
    <Routes>
      
      <Route path='/' element={
        <div className = "App">
          <div className='gradient__bg'>
            <Navbar />
            <Header />
          </div>
          <About />
          <Services />
          <Portfolio />
          <Contact />
          <Footer />
        </div>
      } />
      <Route path='/project1' element = {<Project1 />} />
      <Route path='/project2' element = {<Project2 />} />
      <Route path='/project3' element = {<Project3 />} />
      <Route path='/project4' element = {<Project4 />} />
      <Route path='/project5' element = {<Project5 />} />
      <Route path='/project6' element = {<Project6 />} />
      <Route path='/project7' element = {<Project7 />} />
      <Route path='/contactForm' element = {<ContactForm />} />
      <Route path='/services' element = {<Services />} />
    </Routes>
  )
}

export default App

问题原因

这是单页应用(SPA)部署的典型问题:

  • 本地开发时,React开发服务器会拦截所有路由请求,统一转发到index.html,由React Router在客户端处理路由匹配。
  • 线上服务器默认会根据URL路径查找对应的物理文件,而SPA只有一个index.html,当刷新非根路径(如/contactForm)时,服务器找不到对应文件,返回404。

解决方案

1. 配置服务器重写规则(以Nginx为例)

修改Nginx配置文件,添加try_files指令,将所有请求转发到index.html:

server {
  listen 80;
  server_name your-domain.com;
  root /path/to/your/build/folder; # 替换为你的项目build目录路径
  index index.html;

  location / {
    try_files $uri $uri/ /index.html; # 优先找物理文件,找不到就返回index.html
  }
}

修改后重启Nginx服务生效。

2. 托管平台(Netlify/Vercel)配置

如果部署在Netlify、Vercel这类静态托管平台,无需修改服务器配置,只需添加路由重写规则:

  • Netlify:在项目根目录创建_redirects文件,内容如下:
    /*    /index.html   200
    
  • Vercel:在项目根目录创建vercel.json文件,内容如下:
    {
      "rewrites": [
        { "source": "/(.*)", "destination": "/index.html" }
      ]
    }
    

将文件提交到代码仓库,平台会自动应用规则。

3. 切换React Router为Hash模式

如果不想修改服务器或平台配置,可以将BrowserRouter替换为HashRouter,这种模式会在URL中添加#,所有路由请求都由客户端处理,不会触发服务器的物理文件查找:

import { HashRouter, Routes, Route } from 'react-router-dom';

const App = () => {
  return (
    <HashRouter>
      <Routes>
        {/* 原有的所有路由配置 */}
        <Route path='/' element={...} />
        <Route path='/contactForm' element={<ContactForm />} />
        {/* 其他路由 */}
      </Routes>
    </HashRouter>
  )
}

注意:此方法会改变URL格式(如/contactForm变为/#/contactForm),如果对URL美观性有要求,优先选择前两种方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 16:06:28