How to hot reload without being redirected to root with electron-forge and react
Asked Answered
L

2

8

I'm having a problem with electron-forge, which I imagine is a common problem, but I can't seem to find the answer.

I have created a new project with npx create-electron-app and I have installed and setup react, and it's all working just fine.

The problem I have is with the hot reload. I am using react-router-dom for routing, and I've used the MemoryRouter as obviously, I don't have URL's running an electron app. The hot reload is working out of the box, but each time it reloads I get navigated back to the entry point of the app, and I would like to stay at on the current page. The annoying thing is, I can usually see the current page update for a split second before it navigates my back to root. Is there a setting somewhere to prevent this?

Appreciate any help.

Lurid answered 19/8, 2021 at 13:48 Comment(4)
Can you post a sandbox repo with the memory-router? It will help in figuring things outMarlette
Also can you try logging, window.history between reloads and see what they returnMarlette
What are you using in the backend?Underact
Here is a gist with the Memory Router use gist.github.com/DrLazer/b555ff7226907d0123d97b5fa4d6e8a4Lurid
E
9

Two things that would certainly cause this,

<Switch>
   <Route path="/" component={RootComponent} />
   <Route path="/test" component={TestComponent} />
</Switch>
  1. Check your routes, do you have the base route without exact keyword?

The above will match all routes to the root route and will land you in the root component. You need to add exact key

<Route exact path="/" component={RootComponent} />
  1. Do you have homepage: "." in package.json or <base href="/"> set in index.html? If yes, remove them.

Homepage: '.' will default to serving from the root.

What are the props you have used in the MemoryRouter? Like the initialIndex, initialEntries etc?

Did you try Hot module replacement? I'm not suggesting this as a fix for this issue but it's a good workaround Electron-forge doc for HMR

 entryPoints: [{
          rhmr: 'react-hot-loader/patch', // react hot module replacement
          name: 'main_window',
          html: './src/renderer/index.html',
          js: './src/renderer/index.js'
        }]

Electron-forge doc says it's not possible to do HMR inside the renderer, can you try the above anyways? It worked for me in the webpack app.

Please provide a minimal reproducible code repo/codesandbox to help you with the fix if the above didn't help. Most importantly, need to see the MemoryRouter usage in your app.

Update in response to the comment:

Yes, electron forge does hot reload by default, only changes to the CSS files are hot reloaded (without refresh), changes to JS files will need a refresh, in both cases files are being watched for changes. You can see note in the webpack-dev-server config (snapshot below)

enter image description here

Looking at your gist on MemoryRouter, I suggest below changes

  1. Provide the memory history prop to the router.

        import {createMemoryHistory} from 'history';
    
        const history = createMemoryHistory();
    
        <Router history={history}>
          <Switch>
            <Route path='/dash' exact component={Dash} />
            <Route path='/wallet' exact component={Wallet} />
            <Route path='/service' exact component={ServiceStatus} />
            <Route path='/' exact component={SignIn} />
            <Route component={SignIn} /> // would suggest protected routes 
          </Switch>
        </Router>
    
  2. Remove exact from other routes than the base route and place base above sign-in.

If the issue persists, I suggest you enable the hot module replacement (which would update your app without reload)

Here is an elaborate writeup on Hot Module Replacement applauded by the co-creator of redux and create-react-app.

A gif on HMR taken from above post (No refresh, so no landing on root route on every change yet the app is updated):

enter image description here

An example app to see it in action.

Electron forge HMR solution

Electron forge react example project

Egg answered 26/8, 2021 at 22:0 Comment(5)
Thanks for this answer, it was a good checklist. - I am using exact keyword on the base root - There is no homepage in the package.json - There is no <base> tag in the index.html - No additional attributed on the MemoryRouter About MHR. I was under the impression this was bundles with electron-forge? I mean it does update and reload on save, it just then takes me to the root.Lurid
I've updated the answer in response to your comment. ThanksEgg
Since this reload on update landing in root is annoying, HMR in devserver (forge.config.js) would be a good workaround.Egg
Thanks for the update, again, all good sensible suggestions. History is now provided to the router, reordered as suggested, exact removed from all but the root link. (Yep I'll be adding protected routes, once I get that far.) Same result at the moment. I'll try out the HMR route.Lurid
Most importantly, need to see the MemoryRouter usage in your app.. Replacing BrowserRouter with this solved the problem while using electron react application in case if it helps anybody. Thank you for your answer.Reseda
L
1

You can use electron-reloader to achieve this during development. If changes is made on the main process, the main process gets updated. If changes is made to the renderer process, the renderer process gets updated https://www.npmjs.com/package/electron-reloader

Another approach is to log the current route on the render process and save it on the localstorage. You can then go to that route when the page reloads. If you want to keep the state, you might need to save the state when you log the route.

localStorage.setItem('current_route', route)
localStorage.setItem('current_state, the_entire_state)

You can use the necessary lifecycle, to go to the required route and set the state

Larentia answered 26/8, 2021 at 15:50 Comment(1)
Didn't manage to get electron reloader working without it spewing errosr into the console :( It's an interesting idea the local storage, but it does feel like a hack/workaround for something that should just work. Also doing this I would need to add logic for if the project is running in dev to avoid it in prodLurid

© 2022 - 2024 — McMap. All rights reserved.