0

Problem description:

I am trying to setup a boilerplate app that I can use for creating React front-end apps. I am trying to use React Router and for the most part it works well; however, I'm struggling with any route that has multiple subdirectories but only when I manually type them. For example:

127.0.0.1:8080     ==> Works
127.0.0.1:8080/help     ==> Works
127.0.0.1:8080/level1/level2     ==> fails

When I click on the link from the Header component, it takes me to the route and calls the correct component; however, if subsequently I refresh page (Google Chrome) or simply type the same exact URL, it does not work and the console shows this error (where bundle.js is the file generated by webpack):

GET http://127.0.0.1:8080/level1/bundle.js net::ERR_ABORTED 404 (Not Found) enter image description here

This is the code:

App.js

import React from 'react';
import * as ReactDOMClient from 'react-dom/client';
import AppRouter from './routers/AppRouter';

console.log('app.js is running');

const appRoot = document.getElementById('app');
const root = ReactDOMClient.createRoot(appRoot);
root.render(<AppRouter />);

AppRouter.js

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import DashboardPage from '../components/DashboardPage';
import Header from '../components/Header';
import TwoLevelsPage from '../components/TwoLevels';
import NotFoundPage from '../components/NotFoundPage';

const AppRouter = () => (
  <BrowserRouter>
    <div>
      <Header />
      <Routes>
        <Route path="/" element={<DashboardPage />} />
        <Route path="/help" element={<HelpPage />} />
        <Route path="/level1/level2" element={<TwoLevelsPage />} />
        <Route path="*" element={<NotFoundPage />} />
      </Routes>
    </div>
  </BrowserRouter>
);

export default AppRouter;

Header.js

import React from 'react';
import { NavLink } from 'react-router-dom';

const id = '910';
const getCourse = `/getcourse/${id}`;

const Header = () => (
  <header>
    <h1>THIS IS MY PERSONAL BOILERPLATE APP</h1>
    <NavLink
      to="/"
      className={({ isActive }) => 'nav-link' + (isActive ? ' is-active' : '')}
    >
      Home
    </NavLink>
    <NavLink
      to="/help"
      className={({ isActive }) => 'nav-link' + (isActive ? ' is-active' : '')}
    >
      Help{' '}
    </NavLink>
    <NavLink
      to="/level1/level2"
      className={({ isActive }) => 'nav-link' + (isActive ? ' is-active' : '')}
    >
      L1L2
    </NavLink>
  </header>
);

export default Header;

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Boilerplate</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./bundle.js"></script>
    <p>This is the subtitle straight from HTML</p>
  </body>
</html>

package.json

{
  "name": "boilerplate",
  "version": "1.0.0",
  "main": "index.js",
  "author": "me",
  "license": "MIT",
  "scripts": {
    "build": "webpack",
    "dev-server": "webpack-dev-server"
  },
  "dependencies": {
    "@babel/preset-env": "^7.18.2",
    "@babel/preset-react": "^7.17.12",
    "babel-loader": "^8.2.5",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "node-sass": "^7.0.1",
    "normalize.css": "^8.0.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-modal": "^3.15.1",
    "react-router-dom": "^6.3.0",
    "webpack": "^5.73.0",
    "webpack-dev-server": "^4.9.2"
  },
  "devDependencies": {
    "@babel/cli": "^7.17.10",
    "@babel/core": "^7.18.5",
    "css-loader": "^6.7.1",
    "sass-loader": "^13.0.2",
    "style-loader": "^3.3.1",
    "webpack-cli": "^4.10.0"
  }
}

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        loader: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/,
      },
      {
        test: /\.s?css$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
    ],
  },
  devtool: 'eval-cheap-module-source-map',
  devServer: {
    static: path.join(__dirname, 'public'),
    historyApiFallback: true,
  },
};

Any help would be greatly appreciated. This is my first post so if I didn't provide appropriate information then please let me know.

Thanks in advance!

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Does this help answer your question? https://stackoverflow.com/a/60029709/8690857 Other suggestions seem to include/mention adding a port in the config. – Drew Reese Jun 29 '22 at 22:07
  • Yes, I had looked at the thread and tried several of the suggested solutions and nothing worked. It is just so weird that refreshing or manually typing a route such as "127.0.0.1:8080/help" works just fine but the minute I refresh or manually type "127.0.0.1:8080/level1/level2", it doesn't work. What is it about that second "/" that causes it to behave like that? – Tarek Abdou Jun 30 '22 at 00:54
  • And yes, I did end the dev-server and restart it every time I made a change to the webpack.config.js as I believe that is required. – Tarek Abdou Jun 30 '22 at 01:57
  • OK, somehow I got it to work but I still don't understand why it worked. In the index.html, I removed the "." preceding bundle.js so it now looks like this: I understand that removing the "." from the path makes it an absolute path rather than a relative path but I'm still not sure why that makes a difference in this case. – Tarek Abdou Jun 30 '22 at 04:29
  • Most confusing is why is it that previously (with the leading "." in the path), manually typing the path worked as long as it was at the first level past the root. e.g. 127.0.0.1:8080/help OR 127.0.0.1:8080/contact OR 127.0.0.1:8080/about But it didn't work when there was a subdirectory. e.g. 127.0.0.1:8080/level1/level2 OR 127.0.0.1:8080/user/12345. If anyone can explain this, that would be great! – Tarek Abdou Jun 30 '22 at 04:31

0 Answers0