skip to Main Content

I am using React Router and it works normally in dev environment (localhost) but it doesn’t work on production. When I access, for example: abc.com/products, it will still say Failed to load resource: the server responded with a status of 404 ().
I deployed both the client side and server side on Render.

This is my app.ts on the server side:

import express from 'express';
import cors from 'cors';
import path from 'path';
import apiRouter from './routes/api';

const app = express();

app.use(cors(corsOptions));
app.use(express.json());

app.use(express.static(path.join(__dirname, '../public')));

app.use('/api', apiRouter);

app.get('*', (req, res) => {
    if (!req.url.startsWith('/api')) {
        res.sendFile(path.join(__dirname, '../public', 'index.html'));
    }
});

app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});

This is my App.tsx on the client side:

import React, { useEffect, useState } from 'react';
import Header from './components/Header';
import Menu from './components/Menu';
import Home from './components/Home';
import Products from './components/Products';
import Footer from './components/Footer';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

function App() {

  return (
    <Router>
      <div className="App">
        <Header />
        <Menu />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/products" element={<Products />} />
        </Routes>
        <Footer />
      </div>
    </Router>
  );
}

export default App;

This is my Menu.tsx:

import React, { useState } from "react";
import { Link } from 'react-router-dom';

const Menu = (): JSX.Element => {

    return (
        <div className="menu">
            <div className="main-menu"}>
                <p><span><Link className="redirect" to='/'>HOME</Link></span></p>
                <p className="products-menu"><span><Link className="redirect" to='/products'>PRODUCTS</Link></span></p>
            </div>
        </div>
    );
};

export default Menu;

How should I fix this?

2

Answers


  1. React routers won’t work in that way. you can have a server side rendering application with exact same react code(very minute changes) using NextJS.

    still if you want to serve this in this way, create _redirects file on the root of the project directory and add following lines . This is how I hosted react project on Hostinger (second line is enough if you don’t have any API routes)

    _redirects

    /api/*    /api/:splat    200
    /*        /index.html    200
    
    Login or Signup to reply.
  2. The general idea for hosting/serving your client is that the server should return the root index.html file for all page requests into the app. For Render.com this is accomplished by creating Redirect/Rewrite Rule. See Using Client-Side Routing for details.

    If you use Reach Router or React Router for client-side routing, you
    will need to direct all routing requests to index.html so they can
    be handled by your routing library.

    You can do this easily by defining a Rewrite Rule for your static
    site. Go to the Redirects/Rewrites tab for your service and add a
    rule with the following values:

    Key Value
    Source Path /*
    Destination Path /index.html
    Action Rewrite

    redirect and rewrite rules

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search