Search code examples
javascriptreactjsreact-routerreact-router-dom

React Router v6 - createBrowserRouter Can not get error


I tried to use createBrowserRouter to create a new route (apart from the root "/"), but it seems not working. Can anyone help pointing out what could be missing?

enter image description here

Here is how index.js looks like:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './app';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: "/", // This is working
    element: <App />,
  },
  {
    path: "/hello", // This get "Cannot GET /hello" error 
    element: <div>Hello</div>
  }
])

ReactDOM.createRoot(document.getElementById('root'))
  .render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  )

webpack common config:

const path = require('path');

const babelLoaderRule = {
  test: /\.(js|jsx)$/,
  exclude: /(node_modules|bower_components)/,
  use: {
    loader: 'babel-loader',
    options: {
      presets: ['@babel/preset-env', '@babel/preset-react'],
      plugins: [
        '@babel/plugin-transform-runtime',
        '@babel/plugin-proposal-class-properties',
      ]
    }
  }
}

const urlLoaderRule =  {
  test: /\.(png|jpe?g|gif)$/i,
  loader: 'url-loader',
  options: {
    name: '[name].[ext]',
    outputPath: 'images',
    limit: 8192,
  }
}

module.exports = {
  entry: {
    app: './src/index.js',
  },
  output: {
    filename: 'js/[name]-bundle-[chunkhash:6].js',
    path: path.resolve(__dirname, '../dist'),
  },
  module: {
    rules: [babelLoaderRule, urlLoaderRule]
  }
};

webpack dev config:

const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',
  devServer: {
    static: path.join(__dirname, '../dist'),
    port: 3000,
    compress: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      inject: 'body',
      hash: false,
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
    }),
  ],
  module: {
    rules: [{        
        test: /\.css$/,
        use: [
            'style-loader',
            'css-loader',
            'postcss-loader',
        ]
    }]
  }
});

serve the app by:

"start": "webpack serve --open --config ./config/webpack.dev.config.js",

Solution

  • It appears you are missing actually rendering the router (and routes). Right now the app is only rendering the App component.

    <React.StrictMode>
      <App />
    </React.StrictMode>
    

    Should be

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './app';
    import { createBrowserRouter, RouterProvider } from 'react-router-dom';
    
    const router = createBrowserRouter([
      {
        path: "/",
        element: <App />,
      },
      {
        path: "/hello",
        element: <div>Hello</div>
      }
    ]);
    
    ReactDOM.createRoot(document.getElementById('root'))
      .render(
        <React.StrictMode>
          <RouterProvider router={router} />
        </React.StrictMode>
      );
    

    The dev webpack configuration should also specify historyApiFallback: true in the devServer property.

    const path = require('path');
    const { merge } = require('webpack-merge');
    const common = require('./webpack.common.config.js');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const webpack = require('webpack');
    
    module.exports = merge(common, {
      mode: 'development',
      devtool: 'eval-cheap-module-source-map',
      devServer: {
        historyApiFallback: true, // <--
        static: path.join(__dirname, '../dist'),
        port: 3000,
        compress: true,
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: 'public/index.html',
          inject: 'body',
          hash: false,
        }),
        new webpack.DefinePlugin({
          'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
        }),
      ],
      module: {
        rules: [{        
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader',
                'postcss-loader',
            ]
        }]
      }
    });