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.
In a bid to solve this problem, developers created several plugins and tools that can cause the DOM to re-render on each save without even doing a full-reload. This is called hot reloading. It works by replacing a module of the application during runtime with an updated one so that it's available for instant use.
Once Electron has been successfully installed, Open the package.json file and perform the necessary changes under the scripts key. Install electron-reload using npm and save it as a dev dependency. Install electron-reloader using npm and save it as a dev dependency. Both of these respective packages can be used to implement Hot Reload in Electron.
This is called hot reloading. It works by replacing a module of the application during runtime with an updated one so that it’s available for instant use. This leads us to talk about Hot Module Replacement (HMR). HMR, as the name implies, can replace modules without restarting the server and can easily be enabled with different bundlers.
Install electron-reloader as a development dependency: Then add this line to the index.js file: and that’s it! Now when you start the application using electron ., or npm start if you have in your package.json, any change you apply to the application files will be reflected in the application window.
Lastly, we need to require the react-hot-loader patch into our entry point file: We require this because it’s responsible for patching the code at low-level processing. Let’s test our application to see if the state would be preserved on updates now, we can accomplish this by saving the updates we just made and running the application:
Two things that would certainly cause this,
<Switch>
<Route path="/" component={RootComponent} />
<Route path="/test" component={TestComponent} />
</Switch>
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} />
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)
Looking at your gist on MemoryRouter
, I suggest below changes
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>
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):
An example app to see it in action.
Electron forge HMR solution
Electron forge react example project
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With