Cels
Cels

Reputation: 1334

React Router not working when URL contains multiple paths

I'm using the webpack-dev-server for development and equally react router. This is my wepack configuration.

const webpack = require('webpack');
const path = require('path');
const common = require('./common.config.js')
const merge  = require('webpack-merge')

const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin')

module.exports = merge(common, {
    devtool: 'source-map',
    mode:'development',
    module: {
        rules: [
           {
                test: /\.(sa|sc|c)ss$/,
            use: [
                       {
                  // Adds CSS to the DOM by injecting a `<style>` tag
                  loader: 'style-loader'
                       },
                       {
                          // Interprets `@import` and `url()` like `import/require()` and will resolve them
                          loader: 'css-loader'
                   },
                   {
                          // Loader for webpack to process CSS with PostCSS
                          loader: 'postcss-loader',
                          options: {
                          plugins: function () {
                                return [
                                require('autoprefixer')
                                ];
                                   }
                          }
                       },
               {
                  // Loads a SASS/SCSS file and compiles it to CSS
                  loader: 'sass-loader'
               }
                 ]
           }
        ]
    },
    devServer:{
       contentBase: path.join(__dirname, '../dist'),
       port: 3000,
       proxy:{
          '/api': 'http://127.0.0.1:5000',
       },
       historyApiFallback:true,
       overlay: true,
       stats: 'normal'
    },
    watchOptions: {
       ignored: /node_modules/
    },

    plugins: [
    new CleanWebpackPlugin(['../dist'], { exclude:['sw.js']}),
        new HtmlWebpackPlugin({
            title: 'Script App - Dev',
            filename: '../dist/index.html',
        template:'index_template.html'
        }),
    new MiniCssExtractPlugin({
            filename: 'bundled_styles.css'
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin()    
    ],
});

here is the entry point to my app (where I've defined the routes)

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import {BrowserRouter, Route, Switch} from 'react-router-dom'

import configureStore from './store/configureStore';

import FirstComponent from './FirstComponent';
import SecondComponent from './SecondComponent';
import App from './App';

const store = configureStore();

ReactDOM.render(
    <Provider store={store}>
        <BrowserRouter>
            <App>
               <Switch>
                   <Route path="/first/:a_code" component={FirstComponent} />
                   <Route path="/second" component={SecondComponent} />
               </Switch>
            </App>
        </BrowserRouter>
    </Provider>,

    document.getElementById('root')
);

I'm using react-router v4 and wepack v4.29.

My problem: When I push routes from my code using the history prop, everything works well but when I refresh my browser with the route, Everything goes blank. This behavior is observed only with the route that has multiple paths(/first/:param).

What I've tried: I read from some SO posts that I had to set the historyApiFallback property in my webpack config to true, and I did but it still did not help. One of the comments in this github issue says that historyApiFallback will not work well if certain proxy configurations are available in the webpack config.

I don't want to remove these proxy configurations because I'm making api calls to another server running on a different port.

Can anyone help me on this? Please!

Upvotes: 3

Views: 3416

Answers (2)

Cels
Cels

Reputation: 1334

I actually missed a webpack configuration. I had to add an output configuration and set the publicPath to /. i.e

output:{
  publicPath: '/'
}

I also added the publicPath in the devServer config. i.e

devServer:{
  ...
  publicPath:'/',
  historyApiFallback: true
}

Update:

Equally make sure that your bundle.js script is inserted in your html file like this:

<script src="/bundle.js"></script>

AND NOT

<script src="./bundle.js"></script> OR <script src="bundle.js"></script>

Upvotes: 9

Julian Ignacio
Julian Ignacio

Reputation: 1

I had a similar situation, and I solved using the render: func, that avoids the component to be remounted when the location matches.

So my route look´s like this

<Route
  path="/first/:a_code"
  render={props => 
    <FirstComponent {...props}/>
  }
/>

and then in my component I get the params with match

const first_component = (props) => {
  return (
    <div>
      {props.match.params.a_code}
    </div>
  )
}

at the url "/first/something" I can refresh the browser and still get the desired params, and without any error or blank page. And I don´t believe is a config issue because I didn´t eject the webpack configs in this project so far.

Upvotes: 0

Related Questions