使用 useLocalStorage 实现 electron、网页多窗口 state 同步

2023-03-15 15:31:39 +08:00
 travisyang

前几天发了一个帖子关于如何实现 electron 多窗口开发,发现思路有点问题。今天又想到了可以用 localStorage+hook 的方式。浏览器 window 可以监听 storage 的变化。并用 mobx 来管理状态,当状态值发生变化的时候,往 localStorage 中写入新的序列化后的值。

有评论区大哥说可以封装一个 ipc 的 proxy 。 但是我觉得 ipc 这玩意还是太过复杂,不如把所有的逻辑都放在渲染进程写。

hook 代码

import { autorun, observable } from "mobx";
import { useEffect } from "react";

export const useLocalStorage = <T>(storageKey: string, fallbackState: T) => {
  const state = observable({
    value: JSON.parse(localStorage.getItem(storageKey)) ?? fallbackState,
  });

  autorun(() => {
    localStorage.setItem(storageKey, JSON.stringify(state.value));
  });
  const onStorageUpdate = (e) => {
    const { key, newValue } = e;
    state.value = JSON.parse(newValue);
  };
  useEffect(() => {
    localStorage.setItem(storageKey, JSON.stringify(state.value));
    window.addEventListener("storage", onStorageUpdate);

    return () => {
      window.removeEventListener("storage", onStorageUpdate);
    };
  }, [state.value, storageKey]);

  return [state.value];
};

主窗口

const App = observer(() => {
  const [store, setStore] = useLocalStorage("store", countStore);
  return (
    <div>
      <h1>I am Main Window</h1>
      <button
        onClick={() => {
          const win = window.open("child.html");
        }}
      >
        Open Child Window
      </button>
      <div>store.count = {store.count}</div>
      <button
        onClick={() => {
          store.count--;
        }}
      >
        minus-
      </button>
      <button
        onClick={() => {
          store.count++;
        }}
      >
        plus+
      </button>
    </div>
  );
});

子窗口

const Child = observer(() => {
  const [store, setStore] = useLocalStorage('store', null);

  return (
    <div>
      <h1 onClick={() => {
        store.count ++
      }}>I am Child Window</h1>
      <div>store.count = {store.count}</div>
    </div>
  );
});

效果图

demo 链接:

https://github.com/wxydev1/electron-sync-state

1604 次点击
所在节点    Electron
6 条回复
zsj1029
2023-03-15 16:41:25 +08:00
ruxuan1306
2023-03-15 16:51:59 +08:00
思路有意思学习了。但看起来 useLocalStorage 少返回一个 setStore ,我猜是引入 mobx 后例程忘改了。
travisyang
2023-03-15 17:13:37 +08:00
@ruxuan1306 确实少返回了一个 setStore ,不过 mobx 支持直接修改成员变量触发 ui 更新,所以返回一个值也够了
travisyang
2023-03-15 17:13:59 +08:00
@zsj1029 是的
snowKing66
2023-04-19 09:45:15 +08:00
思路很棒,但是如果要实际运用到工程项目中,我还有点疑问,如果采用这种方式作为窗口通信,不知道效率上跟 ipc 相比如何?因为安全性方便应该是不如 ipc
travisyang
2023-04-19 10:50:03 +08:00
@snowKing66 效率上还没考虑过。其实用 ipc 的话也可以用同样的方式封装成一个 hook 。我一开始只是觉得 ipc 太麻烦了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/924222

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX