# React学习笔记（5）--订阅与发布

By [JamesTsao的个人成长笔记](https://paragraph.com/@pigfly) · 2022-08-05

---

React中的通信方式前面用的比较多的是父子通信。通过父组件将参数作为属性传递给子组件。在编写Web3的前端的时候，不可避免的需要连接钱包，并且需要在组件之间共享钱包的signer以及生成的contract。这个时候，可以把登录按钮写到父组件当中去，然后通过父子通信向子组件传参。比如在父组件中定义一个setState，并把这个setState传递到各个子组件。最开始在父组件中并没有调用这个函数，在子组件中调用setState，就会反过来让父组件重新执行一遍。然后把最新的属性传递到各个子组件当中去。

这种方式在不同子页面之间就不太好传递信息了。另外一种方式是通过订阅发布的形式。将需要共享的变量存储在localStorage中。 并将一个回调函数绑定给对象。每次设置对象的值的时候都会触发相应的回调函数。比如set(address,’address’)，先向localStorage中存入该地址，然后触发address对应的回调函数，对这个新的address进行新建contract并查询该地址的余额。这样就实现了参数的共享。

订阅与发布一般是写在一个store.js文件中。这个模板是通用的，只需要在主程序中调用subscribe的时候实例化callback函数就可以了。

    function setToLocalStorage(key, value) {
      localStorage.setItem(key, JSON.stringify(value));
    }
    function getFromLocalStorage(key) {
      const value = localStorage.getItem(key);
      return JSON.parse(value);
    }
    function removeFromLocalStorage(key) {
      localStorage.removeItem(key);
    }
    
    function Store() {
      let store = getFromLocalStorage("store") || {};
      let subscriptions = {};
    
      function get(name) {
        return store[name];
      }
    
      function set(name, value) {
        store = { ...store, [name]: value };
        setToLocalStorage("store", store);
        if (subscriptions[name] && subscriptions[name].length) {
          subscriptions[name]
            .filter((callback) => callback !== null)
            .forEach((callback) => {
              callback(value);
            });
        }
      }
    
      function subscribe(name, callback) {
        if (!subscriptions[name]) {
          subscriptions[name] = [];
        }
    
        const existing = subscriptions[name].find((cb) => cb === callback);
        if (existing) {
          return () => {};
        }
    
        const length = subscriptions[name].push(callback);
        const index = length - 1;
    
        return () => {
          subscriptions[name][index] = null;
        };
      }
    
      function reset() {
        store = {};
        subscriptions = {};
        removeFromLocalStorage("store");
      }
    
      return { get, set, subscribe, reset };
    }
    
    let storeInstance = {};
    if (typeof window !== "undefined") {
      storeInstance = Store();
    }
    
    const { get, set, subscribe, reset } = storeInstance;
    
    export { get, set, subscribe, reset };
    

这个store.js来自国产良心NFT项目的开源代码。

---

*Originally published on [JamesTsao的个人成长笔记](https://paragraph.com/@pigfly/react-5)*
