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项目的开源代码。