'ElectronJS - sharing redux store between windows?

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.



Solution 1:[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 */ });
});

Solution 2:[2]

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 [email protected] , but for some reason it doesn't in react [email protected]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lmcarreiro
Solution 2 Yosh