Nicolas Ould Bouamama
Nicolas Ould Bouamama

Reputation: 273

React router 404 error when refreshing page with url params

I'm trying to use Url params in react router 5.2.0, something like

    <Switch>
        <Route path="/home" component={ Home } />
        <Route path="/user/:id" component={ User } />
    </Switch >

It's working but when the I'm on a user's page (localhost:8080/user/1) and I refresh the page it'll trigger a 404. I think the issue may come from my webpack config.

If I add publicPath: '/' in the output it'll work but the app is not able to load images anymore, it'll try to access //assets/images/... instead of /assets/images/....

Here is my webpack config:

const HtmlWebPackPlugin = require('html-webpack-plugin')
const ReactIntlPlugin = require('react-intl-webpack-plugin')
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath')
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin')
const fs = require('fs')
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(appDirectory, relativePath)

const publicPath = getPublicUrlOrPath(
    process.env.NODE_ENV === 'development',
    require(resolveApp('package.json')).homepage,
    process.env.PUBLIC_URL
)

const publicUrl = process.env.NODE_ENV === 'development' ? publicPath + "public/assets" : ""
module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.html$/,
                use: [
                    {
                        loader: "html-loader"
                    }
                ]
            },
            {
                test: /\.(png|jpg|gif|svg|ico)$/i,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].[contenthash].[ext]',
                            outputPath: 'assets/img/'
                        }
                    },
                ],
            },
            {
                test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                exclude: [/images/],
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].[ext]',
                            outputPath: 'assets/fonts/'
                        }
                    },
                ],
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    },
    output:{
        filename: 'main.[contenthash].js',
        publicPath: '/' //now I can refresh the page but assets folder is not accessible anymore
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: "./public/index.html",
            filename: "./index.html",
            favicon: "./public/assets/favicon.ico"
        }),
        new ReactIntlPlugin(),
        new InterpolateHtmlPlugin(HtmlWebPackPlugin, {
            PUBLIC_URL: publicUrl,
        }),
        new CleanWebpackPlugin()
    ],
    devServer: {
        historyApiFallback: true
    }
}

Thanks for your help

Upvotes: 0

Views: 477

Answers (1)

Nicolas Ould Bouamama
Nicolas Ould Bouamama

Reputation: 273

I fixed it. So the solution to make the refresh working was to add webpackConfig.output.publicPath = '/' as I tried but the reason why the images were not loading anymore was because in my code I access the images this way:

import Image from '../../images/image.png'

<img src={`/${Image }`} alt="Image"/>

So I just removed the / from src={`/${Image }`} and now it's working and now the images url looks like /assets/images/... instead of //assets/images/...

It was kind of an easy one but I missed it.

Upvotes: 1

Related Questions