Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reload the page gets 404 error using React Router

I have...

Back-End

Node.js/express server which serves files when requests are made to certain routes.

Front-End

React pages that makes calls to the back-end requesting data to populate the pages.

I'm using react-router v4 on the front end. Whenever I navigate to a route that is NOT at the exact path AND reload the page, I get a 404 error. I understand why this isn't working; the browser makes a request to a path handled by react-router, and since it doesn't find that route on the server, I get 404.

I'm seeking for a solution to this problem.

// BrowserRouter imported as Router
<Router>
   <Route exact path='/main' component={Main} />
   <Route path='/sub1' component={SubOne} />
   <Route path='/sub2' component={SubTwo} />
</Router>

When I go to /main in the browser, <Main /> is rendered. Say that inside <Main />, there are links to /sub1 and /sub2 respectively. I click on /sub2. Component and page content renders without fail. Then I refresh page, either by accident or intentionally (say component Sub2 lifts state up to Main).

How do I avoid getting 404 after this refresh? How do I get the page/component where "I was" rendered after a refresh if I'm using React-Router?

like image 331
jsdev17 Avatar asked May 11 '18 00:05

jsdev17


People also ask

How do I fix error 404 in react?

Use a wildcard placeholder to handle 404 page not found in React router, e.g. <Route path="*" element={<PageNotFound />} /> . A route that has an asterisk path * serves as a catch all route. It only matches when no other routes do.

How do I show 404 page in react router?

Routing to the 404 Page You specify the URL path and the element you want to render at that route. The 404 page displays for paths that don't exist on the website. So, instead of specifying the path, use an asterisk (*). Using * renders the NotFound component for all the URLs not specified in routes.

How do I reload the page again in react?

import React from 'react'; function App() { function refreshPage() { window. location. reload(false); } return ( <div> <button onClick={refreshPage}>Click to reload!


2 Answers

I had the same issue you're having about 2 months ago. I had very little knowledge about server-side rendering with React. I got confused on the general concept of it. However, I didn't want to use the create-react-app cli. I wanted to use my own boilerplate. Upon doing research, I found out that I had to configure my webpack to handle my 404 reloading fallbacks.

Here is my current webpack setup:

Please note, only pay attention to the historyApiFallback: true that allows you to refresh your page without throwing a 404 error if you're using v4. In addition, i forgot to mention that this requires webpack-dev-server to work.

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const HtmlWebPackPlugin = require('html-webpack-plugin');

var browserConfig = {
    devServer: {
        historyApiFallback: true,
        proxy: {
            "/api": "http://localhost:3012"
        }
    },
    entry: ['babel-polyfill', __dirname + '/src/index.js'],
    output: {
        path: path.resolve(__dirname + '/public'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    query: {
                        presets: ['react', 'env', 'stage-0']
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: './public/index.html',
        })
    ]
}

var serverConfig = {
    target: 'node',
    externals: [nodeExternals()],
    entry: __dirname + '/server/main.js',
    output: {
        path: path.resolve(__dirname + '/public'),
        filename: 'server.js',
        publicPath: '/'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    query: {
                        presets: ['react', 'env', 'stage-0']
                    }
                }
            }
        ]
    }
}

module.exports = [browserConfig, serverConfig]
like image 139
Curious13 Avatar answered Oct 15 '22 08:10

Curious13


The reason you got 404 is refreshing the page poses network roundtrip to hit the server, while react-router is a client-side routing library, it doesn't handle server-side routing.

when the user hits the refresh button or is directly accessing a page other than the landing page, e.g. /help or /help/online as the web server bypasses the index file to locate the file at this location. As your application is a SPA, the web server will fail trying to retrieve the file and return a 404 - Not Found message to the user.

Since you're using an Express server, connect-history-api-fallback(Express middleware) can be used to proxy all received requests(including unknown ones, /sub2 in your case) through your index page. Then reboot your SPA and route to /sub2 on the client by react router.

If you're using webpack-dev-server for local development, it will be as simple as turning on devServer.historyApiFallback.

like image 21
lxyyz Avatar answered Oct 15 '22 08:10

lxyyz