javascripthtmlelectronipcrendereripcmain

I am getting an error when using ipcRenderer (typeerror cannot read properties of undefined (reading 'send'))


I am getting an error when using ipcRenderer (typeerror cannot read properties of undefined (reading 'send')). I feel the error is in ( const mainWindowTemplate) , I don't know why this error is poping up because the other times I used ipcRenderer this never happened. I am also getting an error for using ipcMain.on in preload.js. I have also sen a screenshot of so many more error caused by these two.Here is the errorhere is one more error

main.js

const electron = require("electron");
const url  = require("url");
const path = require('path');
const { ipcRenderer } = electron;
const {app , BrowserWindow , Menu , IpcMain} = electron;



require('electron-reloader')(module)

let mainWindow;
let windowForAnswer;


function createWindow(){
    mainWindow = new BrowserWindow({
        title: "Aspire Education",
        titleBarStyle: "hiddenInset",
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
            enableRemoteModule: true,
            preload: path.join(app.getAppPath(), 'preload.js'),
        }
    });
    mainWindow.loadURL(url.format({
        pathname: path.join(__dirname , "mainWindow.html"),
        protocol: 'file:',
        slashes: true
    }))
}

app.on('ready' , function(){
    console.log("ready");
    createWindow();
})

function createWindowQuiz(){
    windowForAnswer = new BrowserWindow({
        title: "Quiz",
        titleBarStyle: "hiddenInset",
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
            enableRemoteModule: true,
            preload: path.join(__dirname, 'mainWindow.js'),
        }
    });
    windowForAnswer.loadURL(url.format({
        pathname: path.join(__dirname , "windowForAnswer.html"),
        protocol: 'file:',
        slashes: true
    }))
    
}



const mainMenuTemplate = [
    {
    label: 'File',
    submenu:[
        {
            label:'Start Quiz',
            click(){
              createWindowQuiz();
              ipcRenderer.send("send-questions")
            }
          },
    ]
      
    }   
]




// Add developer tools option if in dev
if(process.env.NODE_ENV !== 'production'){
    mainMenuTemplate.push({
      label: 'Developer Tools',
      submenu:[
        {
          role: 'reload'
        },
        {
          label: 'Toggle DevTools',
          accelerator:process.platform == 'darwin' ? 'Command+I' : 'Ctrl+I',
          click(item, focusedWindow){
            focusedWindow.toggleDevTools();
          }
        }
      ]
    });
  }

menu = Menu.buildFromTemplate(mainMenuTemplate)
Menu.setApplicationMenu(menu)

preload.js

const electron = require('electron')
const url = require('url')
const path = require('path')
const { ipcMain } = require('electron')
const {app , BrowserWindow} = electron

let questions = []
        function Submit() {
            clicked = true
            let question = document.getElementById('question').value;
            let answer = document.getElementById('answer').value;
            if (question.trim() == "" || answer.trim() == "") {
                alert("Question or answer can't be blank")
            } else {
                console.log(question);
                console.log(answer);
                questions.push(question.trim())
                questions.push(answer.trim())
                console.log(questions)
            }
            document.getElementById('question').value = "";
            document.getElementById('answer').value = "";
            return false;
        }

ipcMain.on('send-questions' , () => {
    console.log("Hello World!")
})

Solution

  • You are trying to access ipcMain in the preload script.

    ipcMain is only available in the main process.

    See https://www.electronjs.org/docs/latest/api/ipc-main/

    Which is the reason why ipcMain is undefined and you are getting the error cannot read property on of undefined.

    You are probably looking at something like using ipcRenderer to send a message to the main process and then accessing it using ipcMain.on in the main process.

    So in your preload script:

    ipcRenderer.send('send-questions', {data: questions});
    

    And in your main process:

    ipcMain.on('send-questions', (msg) => {
        console.log(msg.data);
    });