I am trying to implement public, private and unprotected routes in react app (webpack based). We have defined routes where we have added public, private and unprotected routes. The app is loading '/login' by default, but
Whenever we are reloading http://localhost:3000/login
or any component like http://localhost:3000/dashboard
etc, we are getting error
Cannot GET /login
Can someone please suggest some solution?
app.js
const App = () => {
return (
<AuthProvider>
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Navigate to="/login" replace />} />
<Route element={<PublicRoute />}>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
</Route>
<Route element={<PrivateRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
</Route>
<Route path="/home" element={<Home />} />
</Routes>
</Suspense>
</BrowserRouter>
</AuthProvider>
)
};
export default App
AuthContext.js
import React, { createContext, useContext, useState, useEffect } from "react";
const AuthContext = createContext();
export const useAuth = () => useContext(AuthContext);
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(() => {
const savedUser = localStorage.getItem("user");
return savedUser ? JSON.parse(savedUser) : null;
});
useEffect(() => {
const savedUser = localStorage.getItem("user");
if (savedUser) setUser(JSON.parse(savedUser));
}, []);
const login = (userData) => {
setUser(userData);
localStorage.setItem("user", JSON.stringify(userData));
};
const logout = () => {
setUser(null);
localStorage.removeItem("user");
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
publicRoute.js
import React from "react";
import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
const PublicRoute = () => {
const { user } = useAuth();
return !user ? <Outlet /> : <Navigate to="/dashboard" />;
};
export default PublicRoute;
PrivateRoute.js
import React from "react";
import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
const PrivateRoute = () => {
const { user } = useAuth();
return user ? <Outlet /> : <Navigate to="/login" />;
};
export default PrivateRoute;
webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const dotenv = require("dotenv");
const webpack = require("webpack");
// Load environment variables from .env
dotenv.config();
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
// clean: true, // Cleans dist folder before each build
publicPath: "/", // Ensure publicPath is set for proper routing
},
devtool: "source-map",
devServer: {
historyApiFallback: true, // Ensures all requests return index.html
hot: true, // Enables hot module replacement
open: true,
port: 3000, // Change if needed
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
sourceMaps: true, // Ensures Babel generates source maps
},
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|jpg|gif|svg)$/,
type: "asset/resource",
},
],
},
resolve: {
extensions: [".js", ".jsx"],
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html",
inject: true
}),
new webpack.DefinePlugin({
"process.env.REACT_APP_API_BASE_URL": JSON.stringify(process.env.REACT_APP_API_BASE_URL),
}),
],
devServer: {
static: "./dist",
compress: true,
port: 3000,
hot: true,
},
mode: "development",
};
package.json
{
"name": "reactapp",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "webpack serve --config webpack.config.js --mode development",
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"axios": "^1.7.9",
"dotenv": "^16.4.7",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.1.5"
},
"devDependencies": {
"@babel/core": "^7.26.7",
"@babel/preset-env": "^7.26.7",
"@babel/preset-react": "^7.26.3",
"babel-loader": "^9.2.1",
"css-loader": "^7.1.2",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.6.3",
"style-loader": "^4.0.0",
"webpack": "^5.97.1",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.0"
}
}