I'm trying to capture an event in my renderer process (react application) when the electron window is shown in my main.js. I'm unable (to my knowledge) to use the react component lifecycle because the component already mounts on initial load and doesn't update unless state changes, which the electron main process, ShowWindow, triggers neither after initial load.
My use case is to check for new data when the user opens the window from the tray, and trigger a notification. Again, booting the application, closing the tray, and then reopening does not update the state thus prevents me from utilizing the component lifecycle.
So, I'm trying to find a way to send a message from ipcMain to ipcRenderer when the main process shows the window, but am having issues figure out how.
Here's the relevant main.js code:
tray.on('click', function (event) {
toggleWindow()
}
function toggleWindow() {
if (window.isVisible()) {
window.hide()
} else {
showWindow()
}
}
function showWindow() {
const position = getWindowPosition()
window.setPosition(position.x, position.y, false)
window.show()
window.focus()
toggleTrayIcon()
}
Elsewhere in my code, I'm doing something like this to communicate back to the renderer, but in this case, I'm unsure of how to handle the event object:
ipcMain.on('open-finder', function(event, arg) {
let properties = { properties: ['openFile'], filters: [{name: 'Images', extensions: ['jpg', 'png', 'jpeg']}] }
let filePath = dialog.showOpenDialog(window, properties);
let fileData = filePath ? getBase64(filePath[0]) : null
event.sender.send('open-finder-reply', fileData);
});
and then in my react component I want to do something like so (related to above example) to handle that event and trigger my notification:
class Profile extends Component {
constructor(props) {
super(props)
ipcRenderer.on('open-finder-reply', (event, fileData) => {
this.props.updateAvatar(fileData)
});
}
I might be going about this all wrong. Relatively new to Electron. Any help at all would be greatly appreciated. Thank you!
A full example for communication between main and renderer's react component could be something like the following.
For sending ipc message to renderer you can use webContents.send
main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
app.once('ready', () => {
const win = new BrowserWindow()
win.webContents.once('dom-ready', () => {
setTimeout(() => {
win.webContents.send('ready') // send to renderer
}, 3000)
})
win.loadURL(path.join(__dirname, 'renderer.html'))
})
renderer.html
<html>
<head>
<script src="./renderer.js" charset="utf-8"></script>
</head>
<body>
<div id="render"></div>
</body>
</html>
renderer.js
const React = require('react')
const ReactDOM = require('react-dom')
require('babel-register')
const Comp = require('./component')
window.onload = () => {
ReactDOM.render(
React.createElement(Comp),
document.getElementById('render')
)
}
component.js
const { ipcRenderer } = require('electron')
const React = require('react')
module.exports = class extends React.Component {
constructor (props) {
super(props)
this.state = {isReady: false}
ipcRenderer.on('ready', () => {
this.setState({isReady: true})
})
}
render () {
return <p>Is ready: {`${this.state.isReady}`}</p>
}
}
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