【问题标题】:ElectronJS - sharing redux store between windows?ElectronJS - 在 Windows 之间共享 redux 存储?
【发布时间】:2022-04-29 08:31:07
【问题描述】:

我有一个基于electron-react-boilerplate 的电子应用程序。

现在,我已经按照我的意愿运行了一个窗口,我开始创建一个新窗口。

我目前有 2 个 html 文件 - 每个窗口一个 - 包含 div 根:

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

我的 index.js 文件是用于渲染 React 应用程序的响应,如下所示:

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();

它的作用是检查哪个 div 根可用,并呈现适当的组件。

我的问题

如何创建将在 BrowserWindow 实例之间共享的商店?我已经研究了 2 个 npm 包(electron-reduxredux-electron-store),在这种情况下,它们似乎不是我的解决方案。

【问题讨论】:

  • 由于它们是两个不同的窗口,你将无法在它们之间共享 Stores,因为每个窗口都会实例化自己的 Store,每个窗口都是一个单独的进程。
  • @shashi 我实际上找到了electron-redux 的用途。由于我不需要任何操作/reducer 来处理我的主要流程,因此我使用他们在文档中的内容来转发这些操作(他们使用电子的 IPC 功能)并且它工作得非常好:)

标签: javascript reactjs electron


【解决方案1】:

我尝试使用这种非常简单的方法,它几乎可以完美运行,但有时它会冻结(我还不确定究竟是什么让它冻结了)。也许这对任何人都有用,如果有人发现导致冻结问题的原因,请告诉我们。

Redux 存储代码(所有窗口都使用相同的代码):

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

Object.assign(window, { store });

然后我需要从主窗口的渲染器进程中打开新的电子窗口:

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

而且我们在主进程上也需要这段代码:

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 */ });
});

【讨论】:

  • 2 种可能性: - 您创建了商店的副本,并且一个窗口中的更改将不适用于另一个窗口 => 不需要 - 您正在为每次商店更新进行 IPC 调用。 => 大商店很慢
【解决方案2】:

不错的解决方案:

您可以使用 redux-state-sync 这是一个 redux 中间件,用于在多个 react 选项卡之间同步 redux 存储和操作,它与 electron 很好地配合,因为这里的选项卡是不同的渲染器进程。

唯一的障碍是在新创建的窗口中初始化存储,这可以通过从打开新窗口的主窗口使用 ipc 调用发送存储状态来完成,该主窗口调度一个动作来更新状态。

这种初始化方法在 react@17.0.0 中工作得很好,但由于某种原因它没有反应 react@18.0.0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 2023-04-01
    相关资源
    最近更新 更多