2

I have an electron app based on electron-react-boilerplate.

Now, that I have one window running as I wanted it to run, I started to create a new window.

I currently have 2 html files - one for each window - containing div roots:

  1. <div data-root id="main_root"></div>
  2. <div data-root id="second_root"></div>

My index.js file that is response for rendering the react app looks like this:

import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import HomeRoot from './roots/HomeRoot';
import HoverRoot from './roots/HoverRoot';
import { configureStore, history } from './store/configureStore';

const store = configureStore();

const rootMapping = {
  main_root: {
    name: 'HomeRoot',
    Component: HomeRoot,
    getNextRoot: () => require('./roots/HomeRoot'),
  },
  second_root: {
    name: 'SecondRoot',
    Component: SecondRoot,
    getNextRoot: () => require('./roots/SecondRoot'),
  },
};

const renderDesiredRoot = () => {
  const rootElementID = document.querySelector('[data-root]').id;
  const root = rootMapping[rootElementID];
  if (!root) throw Error('There is no such Root component!');
  const { Component, getNextRoot, name } = root;
  render(
    <AppContainer>
      <Component store={store} history={history} />
    </AppContainer>,
    document.getElementById(rootElementID),
  );
  if (module.hot) {
    module.hot.accept(`./roots/${name}`, () => {
      const NextRoot = getNextRoot();
      render(
        <AppContainer>
          <NextRoot store={store} history={history} />
        </AppContainer>,
        document.getElementById(rootElementID),
      );
    });
  }
};

renderDesiredRoot();

What it does, it checks which div root is available, and renders proper components.

My problem

How can I make a store that will be shared accross the BrowserWindow instances? I already looked into 2 npm packages (electron-redux and redux-electron-store) and they do not seem as a solution for me in this case.

mdmb
  • 4,833
  • 7
  • 42
  • 90
  • Since they are two different windows, you will not be able to share Stores between them, because each window will instantiate its own store and each window is a separate process. – shashi Sep 09 '18 at 21:41
  • @shashi I actually found a use for `electron-redux`. Since I do not need any actions/ reducer to work on my main process, I used what they had in their docs to just forward those actions (they use electron's IPC features) and it works perfectly fine :) – mdmb Sep 09 '18 at 21:43

2 Answers2

1

I tried using this very simple approach, it works almost perfectly, but sometimes it's freezing (I'm not sure yet what exactly is making it to freeze). Maybe this could be useful to anyone, and if someone finds out what is causing the freezing issue, please let us know.

Redux store code (this same code is used by all windows):

export const store = window.opener?.store || createStore(...);

Object.assign(window, { store });

Then I need to open new electron window from a renderer process of the main window using:

const newWindow = window.open("/path", "someName");

And we also need this code on the main process:

win.webContents.on("new-window", function (e, url, frameName, _, options) {
  e.preventDefault();

  if (frameName === "someName")
    e.newGuest = new BrowserWindow({ ...options, width: 300, height: 200, /* anything else you wanna add */ });
});
lmcarreiro
  • 5,312
  • 7
  • 36
  • 63
  • 2 possibility : - You create a copy of the store, and changes in one window will not apply to the other window => not wantred - You are making IPC calls for every store update. => very slow for big store – TheToto Nov 26 '21 at 11:18
1

Nice solution:

You can use redux-state-sync which is a redux middleware that used to synchronize the redux store and actions across multiple react tabs, which works nicely with electron as the tabs here are the different renderer process.

The only hindrance is to initialize the store in the newly created window, that can be done by sending the store state with an ipc call from the main window that opens the new one, that dispatches an action to update the state.

This initialization approach works nicely in react@17.0.0 , but for some reason it doesn't in react react@18.0.0

Yosh
  • 39
  • 6