remix-run / react-router

Declarative routing for React
https://reactrouter.com
MIT License
52.93k stars 10.26k forks source link

react-router-dom v5 does not work with electron in production #6726

Closed kyle-mccarthy closed 4 years ago

kyle-mccarthy commented 5 years ago

I'm having an issue using react-router-dom with electron. In development, the router correctly functions and routes users between the different pages. In production, the router no longer functions correctly. In addition to the repo showing the issue, I have some gifs that can quickly outline the problem. Working in development, not working in production.

I am not using redux, and I am using the HashRouter, but I have also tried the MemoryRouter with no luck...

edit I just tested with version 4 of react router dom and it works correctly in production and development. So it seems that this issue is related to version 5.

Version

"electron": "^5.0.0",
"electron-builder": "^20.39.0",
"electron-webpack": "^2.6.2",
"react-router-dom": "^5.0.0"

Test Case

https://github.com/kyle-mccarthy/react-router-dom-electron-issue

Steps to reproduce

The best way to reproduce this error is through the provided github repo.

Expected Behavior

The router should continue to work under the production environment.

Actual Behavior

The router does not correctly work in production.

pshrmn commented 5 years ago

I took a look at the production app and the issue seems to be with the context. The Router receives the new location and re-renders, but the context consumers never get called. It is difficult for me to say what (React Router, React, or Electron) is responsible for the issue.

kyle-mccarthy commented 5 years ago

@pshrmn Thanks for looking into this. I have been digging into it a little more, going from 4.3 to 5, how did the build process change? It looks like if I specify either the import from as "react-router-dom/umd/react-router-dom.js" or "react-router-dom/esm/react-router-dom.js" it works correctly in production and development?

pshrmn commented 5 years ago

v5 switched to a single file build (using Rollup) instead of having many modules. This isn't actually strictly true because the old modules exist with warnings for people who still cherry pick imports, but they will eventually be removed.

What happens if you explicitly import from react-router-dom/cjs/react-router-dom.js? Right now, the index.js module is an if statement that returns different imports in production/development. I'm curious to know what happens when you bypass it.

kyle-mccarthy commented 5 years ago

So I actually stumbled across that which is what led me down this path. In development the (non minified) cjs file works fine, but in production there is an error.

Cannot read property 'exact' of undefined
    at Object.activeStyle (webpack:/node_modules/react-router-dom/cjs/react-router-dom.js:278)

Something equally interesting is that explicitly using "react-router-dom/cjs/react-router-dom.min.js" works in development AND production.

However, while using the normal react-router-dom import I don't think that the production/minfied version of react-router-dom is ever actually used.

I went and changed back my import to just react-router-dom and then edited the index.js file of react-router-dom to the following

"use strict";

if (process.env.NODE_ENV === "production") {
  console.log("react-router-dom PROD");
  module.exports = require("./cjs/react-router-dom.min.js");
} else {
  console.log("react-router-dom DEV");
  module.exports = require("./cjs/react-router-dom.js");
}

When I run the app in dev I get the expected react-router-dom DEV but I also get react-router-dom DEV in production.

One thing to note is that the electron app doesn't actually have NODE_ENV set to production while it runs as a bundled app, but it does have the NODE_ENV as production while it is compiling.

It almost makes me think that both versions of react-router-dom are being included.

dwjohnston commented 5 years ago

@kyle-mccarthy Yeah, I'm getting this exact issue too.

dwjohnston commented 5 years ago

@kyle-mccarthy's solution doesn't work for me though. This is making me cry :cry:

dwjohnston commented 5 years ago

Ok, got this sorted:

The issue was that in some places I was importing (IDE did this for me) Link like:

import { Link } from 'react-router-dom/cjs/react-router-dom';

changing it to:

import { Link } from 'react-router-dom';

solves the issue for me.

jahraphael commented 5 years ago

I'm also encountering the issue kyle-mccarthy mentioned.

I've confirmed the same behavior, that with the latest react router I can run the electron packaged app with NODE_ENV=production and everything works fine. But running it without that will cause all routes to fail.

Their suggested workaround to import from react-router-dom/cjs/react-router-dom worked for me, and I'm able to use that to build working production apps again. (Thanks!)

My relevant dependencies:

"electron": "^5.0.3",
"electron-builder": "^20.43.0",
"electron-compile": "^6.4.2",
"electron-webpack": "^2.6.2",
"react-router-dom": "^5.0.1",
NileDaley commented 5 years ago

I've been folllowing this issue as I've had a similar problem. I've tested in my project and have been able to upgrade to v5.0.0 and the router works in production.

The issue may be that electron-webpack may be breaking react-router-dom in production. You can whitelist react-router-dom to solve this.

Add a electron-webpack.json file containing the following:

{
    "whiteListedModules": ["react-router-dom"]
}

I wasn't able to get it to work with your demo project, but that might be just a difference in build configuration. I hope this was at least some help to you.

For what it's worth, here's my scripts and build config from package.json

{
    "scripts": {
        "dev": "electron-webpack dev",
        "test": "jest",
        "showCoverage": "open coverage/lcov-report/index.html",
        "compile": "electron-webpack",
        "build:mac": "yarn compile && electron-builder --mac --x64",
        "build:win32": "yarn compile && electron-builder --win --ia32"
    },
    "build": {
        "appId": "<my app id>",
        "productName": "<my app name>",
        "directories": {
            "output": "./out/"
        },
        "win": {
            "target": "nsis",
            "asar": false
        },
        "buildVersion": "1.0.0"
    }
}
kimi-chen commented 5 years ago

I've been folllowing this issue as I've had a similar problem. I've tested in my project and have been able to upgrade to v5.0.0 and the router works in production.

The issue may be that electron-webpack may be breaking react-router-dom in production. You can whitelist react-router-dom to solve this.

Add a electron-webpack.json file containing the following:

{
    "whiteListedModules": ["react-router-dom"]
}

I wasn't able to get it to work with your demo project, but that might be just a difference in build configuration. I hope this was at least some help to you.

For what it's worth, here's my scripts and build config from package.json

{
    "scripts": {
        "dev": "electron-webpack dev",
        "test": "jest",
        "showCoverage": "open coverage/lcov-report/index.html",
        "compile": "electron-webpack",
        "build:mac": "yarn compile && electron-builder --mac --x64",
        "build:win32": "yarn compile && electron-builder --win --ia32"
    },
    "build": {
        "appId": "<my app id>",
        "productName": "<my app name>",
        "directories": {
            "output": "./out/"
        },
        "win": {
            "target": "nsis",
            "asar": false
        },
        "buildVersion": "1.0.0"
    }
}

I don't think this work.

AndreyPatseiko commented 5 years ago

Helped this answer.

geeofree commented 5 years ago

Bumping this. My project wasn't working on production when I had react-router-dom@v5.0.1 installed but works when I downgraded to v4.3.1.

tmacwill commented 5 years ago

same here—I'm using a HashRouter in my Electron app packaged with electron-webpack, and Redirect doesn't work with 5.0, but does with 4.3.

Zaynex commented 5 years ago

same again.
current work version

"electron": "5.0.1",
"react-router-dom": "^4.3.1"
Zaynex commented 4 years ago

I want to fix this but I don't know where to start. If anyone is willing to offer advice?

ShirasawaSama commented 4 years ago

It works for me!

I added this at my entry file:

process.env['NODE_' + 'ENV'] = process.env.NODE_ENV

I used Babel to automatically replace the process.env.NODE_ENV to 'production'.

So after compiling, it will become:

process.env['NODE_' + 'ENV'] = 'production'

The react-routr-dom works normally.

My thoughts 🤔

It is possible that incorrect files have been imported or other conditional statements entered in the production due to process.env.NODE_ENV missing.

Most packers, such as Webpack and Parcel, simply replace process.env.NODE_ENV with 'production', but they doesn't apply the value to the process.env.

sibeshkar commented 4 years ago

Here's a quick solution that seems to be working for me. Replaced createBrowserHistory with createHashHistory and everything started working again in production electron app.

import { createHashHistory } from "history";
import { Router } from "react-router-dom";

const history = createHashHistory()

const App = () => {
  return (
          <Router history={history}>
            <Main />
          </Router>
  );

The reason might be described in this StackOverflow issue.

granaber commented 4 years ago

Hi Hackers,

The problem with electron and react-router-dom is that electron when working in production mode (not really) is that you with electron are creating an application, (although it is known that it is a scan with js code running in backgroud), electron does not handle history and works with the synchronized URL, BrowseHistory does not work with electron, therefore you must use HashRouter that if you synchronize your URL with a UI that is (windows.location.hash).

This would be your final code for electron and react-router-dom to work perfectly

// Not BrowserHistory, this for pageweb
import { HashRouter, Route } from "react-router-dom";

class App extends Component {
  render() {
    return (
        <HashRouter> 
          <Route exact={true} 
                  path='/'    
                  render={(props) => 
                          <iLogin {...props}/>
                        }
          />
          <Route path='/InitMenu' component={InitMenu}/>
        </HashRouter>
    );
  }
}

This is the solution ... it is not a problem of versions

Happy Hacking

vazra commented 4 years ago

It's not advisable to use BrowserRouter in electron. Just use HashRouter.

replacing <BrowserRouter> to <HashRouter> should work. 👍

AlekzZz commented 4 years ago

BrowserRouter never worked in electron, everyone mentioned this like 10 times they are using hashrouter, the real solution is what NileDaley said about "whiteListedModules", if you read documentation https://webpack.electron.build/configuration it says:

White-listing Externals¶ Since webpack is set to target the electron environment, all modules are treated as externals. Unfortunately, there can be a few situations where this behavior may not be expected by some modules. For the case of some Vue UI libraries that provide raw *.vue components, they will needed to be white-listed. This ensures that vue-loader is able to compile them as the UI library originally expected.

so I just added all FE dependencies into whiteListedModules, not just react-router-dom and everything works as expected in production.

granaber commented 4 years ago

BrowserRouter never worked in electron, everyone mentioned this like 10 times they are using hashrouter, the real solution is what NileDaley said about "whiteListedModules", if you read documentation https://webpack.electron.build/configuration it says:

White-listing Externals¶ Since webpack is set to target the electron environment, all modules are treated as externals. Unfortunately, there can be a few situations where this behavior may not be expected by some modules. For the case of some Vue UI libraries that provide raw *.vue components, they will needed to be white-listed. This ensures that vue-loader is able to compile them as the UI library originally expected.

so I just added all FE dependencies into whiteListedModules, not just react-router-dom and everything works as expected in production.

False White-listing Externals, if hashrouter works

AlekzZz commented 4 years ago

@granaber i repeat, nobody used BrowserRouter in Electron ever, everybody are already using HashRouter, and It didn't work for me with React Router V5 on production nor it worked for the creator of this thread, he had to downgrade to React Router v4... when you whitelist externals, it works with React Router v5...

WilianZilv commented 4 years ago

In my case, i'm having trouble with the "goBack" function. Lets say the previous route is "/whatever", when i call this function, for some reason, BrowserRouter goes to /C:/whatever. There is another problem with media, in my case, some image source files are just not found even tho the file is there.

All this issues were fixed just by using HashRouter instead of BrowserRouter. Can someone explain the reason?

grimz11 commented 4 years ago

@WilianZilv, Did you solved the issue? HashRouter is not working on my end.

SushilShrestha commented 4 years ago

@WilianZilv, Did you solved the issue? HashRouter is not working on my end.

Replacing <Router> with <HashRouter> worked for me. 🎉

JonFranklin301 commented 4 years ago

It works for me!

I added this at my entry file:

process.env['NODE_' + 'ENV'] = process.env.NODE_ENV

I used Babel to automatically replace the process.env.NODE_ENV to 'production'.

So after compiling, it will become:

process.env['NODE_' + 'ENV'] = 'production'

The react-routr-dom works normally.

My thoughts 🤔

It is possible that incorrect files have been imported or other conditional statements entered in the production due to process.env.NODE_ENV missing.

Most packers, such as Webpack and Parcel, simply replace process.env.NODE_ENV with 'production', but they doesn't apply the value to the process.env.

Hero!

I can confirm this issue is still happening in react-router-dom v5.2.0 when using the HashRouter and electron-webpack.

Putting process.env['NODE_' + 'ENV'] = 'production' as the first line in main/index.js solved this issue. Note that it needs to go in the main process and not the renderer.

lgh06 commented 3 years ago

check your Router basename config near<Router />. check package.json 's homepage field.

zaynekomichi commented 2 years ago

Just use HashRouter, browser router has too many configurations and will end up breaking your code. Proper way of doing it

import * as React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { createRoot } from 'react-dom/client'
import {  Routes, Route, HashRouter } from 'react-router-dom'
import Auth from './AuthenticateUser/authPage';
import Load from './LoadScreen/start';

const App = ()=>{
  return(
    <HashRouter>
      <Routes>
        <Route path = "/" element={ <Load/> } />
        <Route path = "auth" element={ <Auth/>} />
      </Routes>
    </HashRouter>
  )
}
dbatista-docente commented 11 months ago

Top demais @zaynekomichi me salvou aqui em 2023

athanadrian commented 6 months ago

Using react-router-dom version 6, I just used HashRouter instead of BrowserRouter and it worked perfect.


App.js
```js

import { HashRouter as Router, Routes, Route } from 'react-router-dom';

import PageOne from './pages/PageOne';
import PageTwo from './pages/PageTwo';
import Layout from './components/Layout';

const App = () => {

  return (
    <Router>
      <Routes>
        <Route path='/' exact element={<Layout />}>
          <Route path='/page-one' exact element={<PageOne />} />
          <Route path='/page-two' exact element={<PageTwo />} />
        </Route>
      </Routes>
    </Router>
  );
};

export default App;

Layout.js

import { Outlet } from 'react-router-dom';

const Layout = () => {
  return (
    <main className='root'>
      <div className='root-container'>
        <div className='wrapper'>
          <Outlet />
        </div>
      </div>
    </main>
  );
};

export default Layout;
uktamjon-komilov commented 4 months ago

I used vite-electron to create electron react project. I am having the same issue with react-router-dom routing. I tried to use HashRouter but it is not fixing the issue. The project works well in development mode, but when I build for production or when I run the production preview, it is just showing white blank screen and no errors in the developer tools console. Could anyone help me with this issue?

package.json:

{
  "name": "jowi_pos",
  "version": "1.0.0",
  "description": "An Electron application with React and TypeScript",
  "main": "./out/main/index.js",
  "author": "example.com",
  "homepage": "https://electron-vite.org",
  "scripts": {
    "format": "prettier --write .",
    "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
    "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
    "typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false",
    "typecheck": "npm run typecheck:node && npm run typecheck:web",
    "start": "electron-vite preview",
    "dev": "electron-vite dev",
    "build": "taskkill /F /IM electron.exe || true && electron-vite build",
    "postinstall": "electron-builder install-app-deps",
    "build:unpack": "npm run build && electron-builder --dir",
    "build:win": "set ELECTRON_ENABLE_LOGGING=true && npm run build && electron-builder --win",
    "build:mac": "export ELECTRON_ENABLE_LOGGING=true && electron-vite build && electron-builder --mac",
    "build:linux": "export ELECTRON_ENABLE_LOGGING=true && electron-vite build && electron-builder --linux"
  },
  "dependencies": {
    "@alvarosacari/electron-pos-printer": "^1.2.7",
    "@electron-toolkit/preload": "^3.0.0",
    "@electron-toolkit/utils": "^3.0.0",
    "@gravity-ui/date-components": "^1.5.0",
    "@plick/electron-pos-printer": "^1.3.0",
    "@sentry/electron": "^5.0.0",
    "@tanstack/react-query": "^5.24.1",
    "@types/fabric": "^5.3.7",
    "auto-launch": "^5.0.6",
    "axios": "^1.6.4",
    "bindings": "^1.5.0",
    "classnames": "^2.5.1",
    "cors": "^2.8.5",
    "date-fns": "^3.6.0",
    "electron-log": "^5.1.5",
    "electron-pos-printer": "^1.3.6",
    "electron-router-dom": "^1.0.5",
    "electron-settings": "^4.0.4",
    "electron-updater": "^6.2.1",
    "embla-carousel-react": "^8.0.2",
    "express": "^4.19.2",
    "fabric": "^5.3.0",
    "fabricjs-react": "^1.2.2",
    "formik": "^2.4.5",
    "loudness": "^0.4.2",
    "react": "^18.2.0",
    "react-big-calendar": "^1.11.6",
    "react-colorful": "^5.6.1",
    "react-dom": "^18.2.0",
    "react-error-boundary": "^4.0.13",
    "react-international-phone": "^4.2.9",
    "react-router-dom": "^6.21.3",
    "react-toastify": "^10.0.5",
    "sequelize": "^6.37.3",
    "sqlite3": "^5.1.7",
    "yup": "^1.3.3",
    "zustand": "^4.4.7"
  },
  "devDependencies": {
    "@electron-toolkit/eslint-config-prettier": "^2.0.0",
    "@electron-toolkit/eslint-config-ts": "^1.0.1",
    "@electron-toolkit/tsconfig": "^1.0.1",
    "@gravity-ui/uikit": "^5.30.1",
    "@types/lodash": "^4.17.0",
    "@types/node": "^18.19.9",
    "@types/react": "^18.2.48",
    "@types/react-big-calendar": "^1.8.9",
    "@types/react-dom": "^18.2.18",
    "@vitejs/plugin-react": "^4.2.1",
    "autoprefixer": "^10.4.17",
    "electron": "^28.2.0",
    "electron-builder": "^24.13.3",
    "electron-vite": "^2.0.0",
    "eslint": "^8.56.0",
    "eslint-plugin-react": "^7.33.2",
    "file-loader": "^6.2.0",
    "postcss": "^8.4.35",
    "prettier": "^3.2.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "tailwindcss": "^3.4.1",
    "typescript": "^5.3.3",
    "url-loader": "^4.1.1",
    "vite": "^5.0.12",
    "webpack": "^5.90.3"
  }
}

main/index.ts:

import { join } from "path";
import { Server } from "http";
import { sequelize } from "./printers/db";
import { createExpressApp } from "./express";
import { setupShortcuts } from "./shortcuts";
import icon from "../../resources/icon.png?asset";
import { app, shell, BrowserWindow } from "electron";
import { optimizer, is } from "@electron-toolkit/utils";
import { setupSettingsHandlers } from "./ipcHandlers/settings";
import { setupVolumeHandlers } from "./ipcHandlers/volume";
import { setupPOSHandlers } from "./ipcHandlers/pos";
import {
  fetchPrintersInterval,
  setupPrinterHandlers,
} from "./ipcHandlers/printers";
import { setupSentry } from "./sentry";

let window: BrowserWindow | null = null;
let expressServer: Server | null = null;

setupSentry();

function killProcesses() {
  sequelize.close();

  if (fetchPrintersInterval) {
    clearInterval(fetchPrintersInterval);
  }
  if (expressServer) {
    expressServer.close();
  }

  window = null;
}

function createWindow(): void {
  window = new BrowserWindow({
    width: 1000,
    height: 600,
    show: false,
    autoHideMenuBar: true,
    ...(process.platform === "linux" ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, "../preload/index.js"),
      sandbox: false,
    },
  });

  window.on("ready-to-show", () => {
    window?.webContents.setZoomFactor(1);
    window?.show();
    window?.webContents.openDevTools({ mode: "detach", activate: true });
  });

  window.on("closed", () => {
    killProcesses();
  });

  window.webContents.setWindowOpenHandler((details) => {
    console.log(details.url);
    shell.openExternal(details.url);
    return { action: "deny" };
  });

  if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
    window.loadURL(process.env["ELECTRON_RENDERER_URL"]);
  } else {
    window
      .loadFile(join(__dirname, "../renderer/index.html"), { hash: "main" })
      .catch((err) => {
        console.error("Failed to load the index.html:", err);
      });
  }

  setupShortcuts(window);
}

app.whenReady().then(async () => {
  app.on("browser-window-created", (_, window) => {
    optimizer.watchWindowShortcuts(window);
  });

  app.on("activate", function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });

  app.on("before-quit", () => {
    killProcesses();
  });

  setupPOSHandlers();
  setupVolumeHandlers();
  setupSettingsHandlers(app);
  setupPrinterHandlers(app);

  createWindow();

  expressServer = await createExpressApp(window);
});

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    killProcesses();
    app.quit();
  }
});

preload/index.ts:

import { contextBridge } from "electron";
import { electronAPI } from "@electron-toolkit/preload";

const api = {};

if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld("electron", electronAPI);
    contextBridge.exposeInMainWorld("api", api);
  } catch (error) {
    console.error(error);
  }
} else {
  // @ts-ignore (define in dts)
  window.electron = electronAPI;
  // @ts-ignore (define in dts)
  window.api = api;
}

renderer/main.tsx:

import "./global.css";
import { App } from "./App";
import { setupSentry } from "./sentry";
import ReactDOM from "react-dom/client";
import { queryClient } from "./queryClient";
import "@gravity-ui/uikit/styles/fonts.css";
import "@gravity-ui/uikit/styles/styles.css";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import { QueryClientProvider } from "@tanstack/react-query";
import { configure, ThemeProvider, ToasterProvider } from "@gravity-ui/uikit";

setupSentry();

configure({
  lang: "ru",
});

ReactDOM.createRoot(document.getElementById("root")!).render(
  <ThemeProvider theme="light">
    <ToasterProvider>
      <QueryClientProvider client={queryClient}>
        <App />
        <ToastContainer />
      </QueryClientProvider>
    </ToasterProvider>
  </ThemeProvider>,
);

renderer/App.tsx:

import React from "react";
import AuthLayout from "./sections/auth";
import LoginPage from "./sections/auth/login";
import SplashPage from "./sections/auth/splash";
import LoginMethod from "./sections/auth/loginMethod";
import TerminalsPage from "./sections/auth/terminals";
import SearchDevice from "./sections/auth/searchDevice";
import { HashRouter, Routes, Route } from "react-router-dom";

export function App() {
  return (
    <HashRouter>
      <Routes>
        <Route path="/" element={<AuthLayout />}>
          <Route path="auth" element={<React.Fragment />}>
            <Route path="method" element={<LoginMethod />} />
            <Route path="search" element={<SearchDevice />} />
            <Route path="terminals" element={<TerminalsPage />} />
            <Route path="login" element={<LoginPage />} />
          </Route>

          <Route index element={<SplashPage />} />
        </Route>
      </Routes>
    </HashRouter>
  );
}
zaynekomichi commented 4 months ago

I haven't used Electron in awhile but I do remember facing errors because of the sqlite I needed to have MS build tools installed for it to build a working app. Just a thought!

PS Migrated to using Tauri fewer headaches

CrisAlejo26 commented 1 month ago

Hola, quizás sea algo tarde pero funcionara para el futuro, yo lo pude solucionar de la siguiente forma y es 29/08/2024 con la ultima versión de react, de react-router-dom, electron y vite me funciono en produccion y en desarrollo, aquí defino las rutas:

 import { Sidebar } from './components';
    import {
        CompletarInformeScreen,
        ConfiguracionesScreen,
        Dashboard,
        EditarInformeScreen,
        InformacionCamposScreen,
    } from './screens';
    import { createHashRouter, RouterProvider } from 'react-router-dom';

    const router = createHashRouter([
        {
            path: '/',
            element: <Dashboard />,
        },
        {
            path: '/completar_informe',
            element: <CompletarInformeScreen />,
        },
        {
            path: '/configuraciones',
            element: <ConfiguracionesScreen />,
        },
        {
            path: '/editar_informe',
            element: <EditarInformeScreen />,
        },
        {
            path: '/informacion_campos',
            element: <InformacionCamposScreen />,
        },
    ]);

    function App(): JSX.Element {
        // const ipcHandle = (): void => window.electron.ipcRenderer.send('ping');

        return (
            <div className="min-h-screen bg-gray-100">
                <div className="flex">
                    <Sidebar />
                    <div className="p-3">
                        <RouterProvider router={router} />
                    </div>
                </div>
            </div>
        );
    }
export default App;

Esta es la navbar, noten que pongo un # antes:

import logoAutoFillAI from '../../assets/logo.svg';
    import { MdOutlineDashboard } from 'react-icons/md';
    import { FaRegEdit } from 'react-icons/fa';
    import { IoDocumentTextOutline } from 'react-icons/io5';
    import { IoSettingsOutline } from 'react-icons/io5';
    import { SidebarItem } from './SidebarItem';
    import { RiInputField } from 'react-icons/ri';
    import { PropsSidebarItem } from '@renderer/interfaces';

    const itemsSideBar: PropsSidebarItem[] = [
        {
            icon: MdOutlineDashboard,
            title: 'Dashboard',
            path: '#/',
        },
        {
            icon: IoDocumentTextOutline,
            title: 'Completar informe',
            path: '#/completar_informe',
        },
        {
            icon: FaRegEdit,
            title: 'Editar informe',
            path: '#/editar_informe',
        },
        {
            icon: RiInputField,
            title: 'Información de campos',
            path: '#/informacion_campos',
        },
    ];

    const settings: PropsSidebarItem = {
        icon: IoSettingsOutline,
        title: 'Configuraciones',
        path: '#/configuraciones',
    };

    export const Sidebar = () => {
        return (
            <div className="h-screen w-44 bg-[#0046FE] pt-4 p-2 flex flex-col justify-between">
                <div>
                    <figure className="w-24 mx-auto mb-10">
                        <img src={logoAutoFillAI} alt="Logo" />
                    </figure>
                    {itemsSideBar.map((item, index) => (
                        <SidebarItem key={index} {...item} />
                    ))}
                </div>
                <SidebarItem {...settings} />
            </div>
        );
    };

Este es main/index.ts el cual no modifique nada para hacer funcionar la navegación:

import { app, Shell, BrowserWindow, ipcMain } from 'electron';
    import { join } from 'path';
    import { electronApp, optimizer, is } from '@electron-toolkit/utils';
    import icon from '../../resources/icon.png?asset';

    function createWindow(): void {
        // Create the browser window.
        const mainWindow = new BrowserWindow({
            width: 900,
            titleBarStyle: 'hidden',
            titleBarOverlay: {
                color: '#f3f4f6',
                symbolColor: '#74b1be',
                height: 30,
            },
            height: 670,
            show: false,
            autoHideMenuBar: true,
            ...(process.platform === 'linux' ? { icon } : {}),
            webPreferences: {
                preload: join(__dirname, '../preload/index.js'),
                sandbox: false,
            },
        });

        mainWindow.on('ready-to-show', () => {
            mainWindow.show();
        });

        mainWindow.webContents.setWindowOpenHandler(details => {
            shell.openExternal(details.url);
            return { action: 'deny' };
        });

        if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
            mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']);
        } else {
            mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
        }

        // HMR for renderer base on electron-vite cli.
        // Load the remote URL for development or the local html file for production.
        if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
            mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']);
        } else {
            mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
        }
    }

    // This method will be called when Electron has finished
    // initialization and is ready to create browser windows.
    // Some APIs can only be used after this event occurs.
    app.whenReady().then(() => {
        // Set app user model id for windows
        electronApp.setAppUserModelId('com.electron');

        // Default open or close DevTools by F12 in development
        // and ignore CommandOrControl + R in production.
        // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
        app.on('browser-window-created', (_, window) => {
            optimizer.watchWindowShortcuts(window);
        });

        // IPC test
        ipcMain.on('ping', () => console.log('pong'));

        createWindow();

        app.on('activate', function () {
            // On macOS it's common to re-create a window in the app when the
            // dock icon is clicked and there are no other windows open.
            if (BrowserWindow.getAllWindows().length === 0) createWindow();
        });
    });

    // Quit when all windows are closed, except on macOS. There, it's common
    // for applications and their menu bar to stay active until the user quits
    // explicitly with Cmd + Q.
    app.on('window-all-closed', () => {
        if (process.platform !== 'darwin') {
            app.quit();
        }
    });

    // In this file you can include the rest of your app"s specific main process
    // code. You can also put them in separate files and require them here.

Observaciones:

El Link de navegación entre paginas no funciona, debe ser con la etiqueta