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?
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",
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',
]
}]
}
});