title: Why is my ipcMain not sending to ipcRenderer in Electron?
body: <p>New to electron I've figured out how to send from <em>Renderer</em> to <em>Main</em> but I'm trying to learn how to go from <em>Main</em> to <em>Renderer</em>. In my research I've read:</p>
  
  <p><a href="https://discuss.atom.io/t/ipc-send-from-main-process-to-renderer/16046" rel="nofollow noreferrer">IPC send from main process to renderer</a> and tried:</p>
  
  <p><em>main.js</em>:</p>
  
  <pre><code>const { app, ipcMain, Menu }  = require('electron')
  const appVersion = process.env.npm_package_version
  const mainWindow = require('./renderer/mainWindow')
  
  app.on('ready', () =&gt; {
    mainWindow.createWindow(),
    console.log(`Trying to send app version to renderer: ${appVersion}`),
    mainWindow.webContents.send('app-version', appVersion),  
    Menu.setApplicationMenu(mainMenu)
  })
  </code></pre>
  
  <p>but I get an error of:</p>
  
  <blockquote>
    <p>Uncaught Exception TypeError Cannot read property 'send' of undefined</p>
  </blockquote>
  
  <p>After reading "<a href="https://stackoverflow.com/questions/47597982/send-sync-message-from-ipcmain-to-ipcrenderer-electron">Send sync message from IpcMain to IpcRenderer - Electron</a>" I tried:</p>
  
  <pre><code>ipcMain.on('app-version', (event) =&gt; {
      console.log(`Sent: ${appVersion}`)
      event.sender.send(appVersion)
  }),
  </code></pre>
  
  <p>but nothing happens or errors out. My <em>renderer.js</em>:</p>
  
  <pre><code>const { ipcRenderer } = require('electron')
  ipcRenderer.on('app-version', (event, res) =&gt; {
      console.log(res)
  })
  </code></pre>
  
  <p>Why is my <em>ipcMain</em> not sending to my <em>ipcRenderer</em>?</p>
  
  <h2>Edit:</h2>
  
  <p><em>mainWindow.js</em>:</p>
  
  <pre><code>// Modules
  const { BrowserWindow } = require('electron')
  
  // export mainWindow
  exports.createWindow = () =&gt; {
  
    // BrowserWindow options
    // https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
    this.win = new BrowserWindow({
        minWidth: 400,
        minHeight: 400,
        frame: false,
        webPreferences: {
          nodeIntegration: true,
          backgroundThrottling: false
        }
    })
  
    // Devtools
    this.win.webContents.openDevTools()
  
    // Load main window content
    this.win.loadURL(`file://${__dirname}/index.html`)
  
    // Handle window closed
    this.win.on('closed', () =&gt; {
      this.win = null
    })
  }
  </code></pre>
  
  <p>I've also tried:</p>
  
  <p><em>main.js</em>:</p>
  
  <pre><code>app.on('ready', () =&gt; {
    mainWindow.createWindow(),
    mainWindow.win.webContents.send('app-version', appVersion),  
    Menu.setApplicationMenu(mainMenu)
  })
  </code></pre>
  
  <p><em>renderer.js</em>:</p>
  
  <pre><code>console.log("Trying")
  ipcRenderer.on('app-version', (args) =&gt; {
      console.log(`Node version is ${args}`)
  })
  </code></pre>
  
  <p>For some reason now the applied answer I've written ipcMain sends to renderer several times and renders the console message repeatedly</p>
  
  <pre><code>Trying to send app version to renderer: 1.0.0
  Trying to send app version to renderer: 1.0.0
  Trying to send app version to renderer: 1.0.0
  Trying to send app version to renderer: 1.0.0
  Trying to send app version to renderer: 1.0.0
  </code></pre>
  
  <p>Now the application flashes but in the <code>console.log</code> it shows it once and I do not understand why.</p>
  
  <h2>Edit</h2>
  
  <p>To respond to the <a href="https://stackoverflow.com/a/55281921/1952287">answer</a>.</p>
  
  <p>I'm aware of <code>app.getVersion</code> I was just using <code>ENV</code> to learn how to send to main. After testing the code this approach doesn't work.</p>
  
  <p>Coping this:</p>
  
  <pre><code>app.on('ready', () =&gt; {
      const win = mainWindow.createWindow(),
      console.log(`Trying to send app version to renderer: ${appVersion}`),
      win.webContents.send('app-version', appVersion),  
      Menu.setApplicationMenu(mainMenu)
  })
  </code></pre>
  
  <p>throws the error of:</p>
  
  <blockquote>
    <p>Missing initializer in const declaration</p>
  </blockquote>
  
  <p>so modified to this:</p>
  
  <pre><code>app.on('ready', () =&gt; {
    const win = mainWindow.createWindow()
    console.log(`Trying to send app version to renderer: ${appVersion}`)
    win.webContents.send('app-version', appVersion)
    Menu.setApplicationMenu(mainMenu)
  })
  </code></pre>
  
  <p>but when adding the return at the end of <code>exports.createWindow</code> throws this error of:</p>
  
  <blockquote>
    <p>win is not defined</p>
  </blockquote>
  
  <p>adding <code>let.win</code> before <code>exports.createWindow</code> will not throw a code but nothing is sent over.</p>
  
  <hr>
  
  <h2><a href="https://github.com/electron/fiddle" rel="nofollow noreferrer">Electron Fiddle</a></h2>
  
  <p><em>index.html:</em></p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;meta charset="UTF-8"&gt;
      &lt;title&gt;Electron learning&lt;/title&gt;
      &lt;!-- CSS Bootstrap --&gt;
      &lt;!-- &lt;link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.css"&gt; --&gt;
      &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"&gt;
  
      &lt;!-- 
        Font Awesome 
        https://fontawesome.com/v4.7.0/cheatsheet/ 
      --&gt;
      &lt;!-- &lt;link rel="stylesheet" href="../node_modules/font-awesome/css/font-awesome.css"&gt; --&gt;
      &lt;link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"&gt;
  
      &lt;!-- Custom CSS --&gt;
      &lt;style&gt;
        body {
          -webkit-app-region: drag;
        }
        footer {
          position: fixed;
          bottom: 0;
          width: 100%;
        }
        #close_app,
        #site {
          cursor: pointer;
        }
      &lt;/style&gt;
    &lt;/head&gt;
    &lt;body class="d-flex flex-column h-100"&gt;
      &lt;header&gt;
        &lt;nav class="navbar navbar-expand navbar-dark fixed-top bg-dark"&gt;
          &lt;a class="navbar-brand text-white"&gt;Foobar&lt;/a&gt;
          &lt;div class="collapse navbar-collapse justify-content-between"&gt;
            &lt;div class="navbar-nav"&gt;
              &lt;a id="site" class="nav-link"&gt;&lt;small&gt;&lt;u id="application"&gt;&lt;/u&gt;&lt;/small&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class="navbar-nav"&gt;
                &lt;a id="close_app" class="nav-item nav-link"&gt;&lt;i class="fa fa-times-circle"&gt;&lt;/i&gt;&lt;/a&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/nav&gt;
      &lt;/header&gt;
  
      &lt;main role="main" class="flex-shrink-0"&gt;
      &lt;div class="container"&gt;
        &lt;h1&gt;Hello World!&lt;/h1&gt;
        &lt;!-- All of the Node.js APIs are available in this renderer process. --&gt;
        We are using Node.js &lt;script&gt;document.write(process.versions.node)&lt;/script&gt;,
        Chromium &lt;script&gt;document.write(process.versions.chrome)&lt;/script&gt;,
        and Electron &lt;script&gt;document.write(process.versions.electron)&lt;/script&gt;.
        Electron app version &lt;script&gt;document.write(process.versions.electron)&lt;/script&gt;.
      &lt;/div&gt;
      &lt;p id="testSender"&gt;&lt;/p&gt;
      &lt;/main&gt;
  
      &lt;footer class="footer mt-auto py-3 "&gt;
      &lt;div class="container"&gt;
        &lt;span class="text-muted"&gt;Place sticky footer content here.&lt;/span&gt;
      &lt;/div&gt;
    &lt;/footer&gt;
      &lt;script&gt;
          // jQuery
          // window.jQuery = window.$ = $ = require('jquery')
  
          // You can also require other files to run in this process
          require('./renderer.js')
      &lt;/script&gt;
      &lt;!-- &lt;script src="../node_modules/jquery/dist/jquery.min.js"&gt;&lt;/script&gt; --&gt;
      &lt;script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"&gt;&lt;/script&gt;
  
  
      &lt;!-- &lt;script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"&gt;&lt;/script&gt; --&gt;
      &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"&gt;&lt;/script&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><em>main.js:</em></p>
  
  <pre><code>'use strict'
  
  // Modules to control application life and create native browser window
  const { app, ipcMain, BrowserWindow, Menu }  = require('electron')
  const testMainSend = `Trying to send something to renderer`
  
  let mainWindow
  
  // Window state keeper
  const windowStateKeeper = require('electron-window-state')
  
  // export mainWindow
  function createWindow () {
  
    let winState = windowStateKeeper({
      defaultWidth: 400,
      defaultHeight: 400
    })
  
    // BrowserWindow options
    // https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
    const win = new BrowserWindow({
      width: winState.width,
      height: winState.Height,
      x: winState.x,
      y: winState.y,
      minWidth: 400,
      minHeight: 400,
      frame: false,
      webPreferences: {
        nodeIntegration: true,
        backgroundThrottling: false
      }
    })
  
    winState.manage(win)
  
    // Devtools
    win.webContents.openDevTools()
  
    // Load main window content
    win.loadURL(`file://${__dirname}/index.html`)
  
    // Handle window closed
    win.on('closed', () =&gt; {
        this.win = null
    })
  
    return win
  }
  
  // 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.on('ready', () =&gt; {
    createWindow()
  
    // 1st attempt
    // webContents.send('misc-sender', testMainSend)
  
    // 2nd attempt
    // const win = createWindow()
    // win.webContents.send('misc-sender', testMainSend)
  
    // 3rd attempt
    const win = createWindow()
    win.webContents.on('dom-ready', () =&gt; {
      console.log(`Trying to send renderer: ${testMainSend}`)
      mainWindow.win.webContents.send('misc-sender', testMainSend)
    })
  })
  
  // Quit when all windows are closed.
  app.on('window-all-closed', () =&gt; {
    // On macOS it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
      app.quit()
    }
  })
  
  app.on('activate', () =&gt; {
    // 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 (mainWindow === null) {
      createWindow()
    }
  })
  
  // Close application from button
  ipcMain.on('closing-app', () =&gt; {
    app.quit()
    console.log('Closed app from font awesome link')
  })
  </code></pre>
  
  <p><em>renderer.js:</em></p>
  
  <pre><code>// This file is required by the index.html file and will
  // be executed in the renderer process for that window.
  // All of the Node.js APIs are available in this process.
  const { ipcRenderer, shell } = require('electron')
  const appVersion = require('electron').remote.app.getVersion()
  
  // Devtron
  // require('devtron').install()
  
  // Close App
  const closeApp = document.getElementById('close_app')
  closeApp.addEventListener('click', () =&gt; {
      ipcRenderer.send('closing-app')
  })
  
  // received from ipcMain test
  ipcRenderer.on('misc-sender', (event, args) =&gt; {
      appendTest = document.getElementById('testSender')
      appendTest.innerHTML += args
  })
  
  // Getting version
  const appVersioning = document.getElementById('application')
  appVersioning.innerHTML = appVersion
  
  // Open site
  const homeURL = document.getElementById('site')
  homeURL.addEventListener('click', (e) =&gt; {
      e.preventDefault
      shell.openExternal("https://www.google.com/")
  })
  </code></pre>