reactjselectronipcrenderer

Using window.require('electron') in a render function causes the whole screen to go blank. Electron, React, Material UI


I am attempting to build a program using Electron, React.js, and Material UI. I can get the app to open, and the screen to show as intended. However, when I attempt to use ipcRender in a render component the entire screen goes blank. I can verify that this is the line of code that causes issues because simply commenting it out will bring everything back. I require this feature to make a custom app bar.

I have tried removing window. from the require statement in the render function, but that stops react and throws an error. I have also tried setting nodeIntegration: true however this makes no change.

This is the main file.

// Modules to control application life and create native browser window
const {app, BrowserWindow, Tray, nativeImage, ipcMain} = require('electron')
const path = require('path')
const Store = require('electron-store')

let tray, window

function createWindow () {
  // Create the browser window.
  window = new BrowserWindow({
    width: 800,
    height: 600,
    show: true,
    frame: true,
    title: 'Nozdive Program',
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false
    }
  })

  window.on('closed', () => window = null)

  // and load the index.html of the app.
  window.loadURL('http://localhost:3000')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

const createTray = () => {
  const icon = path.join(__dirname, 'assets/nozdive.png')
  const nImage= nativeImage.createFromPath(icon)

  tray = new Tray(nImage)
  tray.on('click', (event) => toggleWindow())
}

const toggleWindow = () => {
  window.isVisible() ? window.hide() : window.show()
}


// 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(() => {
  ipcMain.on('minimize-event', ()  => window.minimize())
  createTray()
  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', function () {
  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.

const store = new Store()

Here is the render function.

import React, {useState} from 'react'
import { Box, Typography } from '@mui/material'
import MenuIcon from '@mui/icons-material/Menu';
import CloseIcon from '@mui/icons-material/Close';
import FullscreenIcon from '@mui/icons-material/Fullscreen';
import MinimizeIcon from '@mui/icons-material/Minimize';
// import FullscreenExitIcon from '@mui/icons-material/FullscreenExit';
import colors from '../config/colors';

const {ipcRenderer} = window.require('electron')

export default function TitleBar({toggleDrawer}) {
  const [isActive, setIsActive] = useState()
  const [isminimized, setIsminimized] = useState()
  const [isFullScreen, setIsFullScreen] = useState(false)

  const handleMinimize = () => {
    toggleDrawer()
    // ipcRenderer.invoke('minimize-event')
  }

  const toggleIsFullScreen = () => {
    const state = isFullScreen
    setIsFullScreen(!state)
  }

  const handleClose = () => {
    toggleDrawer()
  }

  return (
    <Box sx={styles.headerBox}>
      <MenuIcon 
        sx={styles.headerFont}
        onClick={toggleDrawer}
      />
      <Box sx={styles.textbox}>
        <Typography sx={styles.headerFont}>Nozdive's Program!</Typography>
      </Box>
      <Box sx={styles.windowControl}>
          <MinimizeIcon 
            sx={styles.headerFont}
            onClick={handleMinimize}
          />
          <FullscreenIcon 
            sx={styles.headerFont}
            onClick={toggleIsFullScreen}
          />
          <CloseIcon 
            sx={styles.headerFont}
            onClick={handleClose}
          />
      </Box>
    </Box>
  )
}

const styles = {
  headerBox: {
    alignItems: 'center',
    backgroundColor: colors.secondary,
    display: 'flex',
    height: 30,
    width: '100vw',
  },
  headerFont: {
    color: colors.tertiary,
    fontSize: 30,
    padding: 1,
  },
  textbox: {
    display: 'flex',
    width: '100vw',
    alignItems: 'center',
    justifyContent: 'center',
  },
  windowControl: {
    display: 'flex',
    justifyContent: 'center',
  },
}


Solution

  • You should add the code below in preload.js

    const { ipcRenderer } = require("electron");
    
    process.once("loaded", () => {
      window.ipcRenderer = ipcRenderer;
    });