crootfast
Version:
大前端工程化命令行脚手架
61 lines (57 loc) • 1.78 kB
JavaScript
import { useRef } from "react";
// import isPlainObject from 'lodash/isPlainObject';
import { isPlainObject } from "lodash-es";
import { useCreation, useUpdate } from "ahooks";
// k:v 原对象:代理过的对象
const proxyMap = new WeakMap();
// k:v 代理过的对象:原对象
const rawMap = new WeakMap();
function observer(initialVal, cb) {
let existingProxy = proxyMap.get(initialVal);
// 添加缓存 防止重新构建proxy
if (existingProxy) {
return existingProxy;
}
// 防止代理已经代理过的对象
// https://github.com/alibaba/hooks/issues/839
if (rawMap.has(initialVal)) {
return initialVal;
}
let proxy = new Proxy(initialVal, {
get: function (target, key, receiver) {
let res = Reflect.get(target, key, receiver);
// Only proxy plain object or array,
// otherwise it will cause: https://github.com/alibaba/hooks/issues/2080
return isPlainObject(res) || Array.isArray(res) ? observer(res, cb) : res;
},
set: function (target, key, val) {
const oVal = target[key];
if (oVal === val) {
// console.log(`尝试设置 ${key},但新旧值相同,无需设置`);
return true;
}
let ret = Reflect.set(target, key, val);
cb();
return ret;
},
deleteProperty: function (target, key) {
let ret = Reflect.deleteProperty(target, key);
cb();
return ret;
}
});
proxyMap.set(initialVal, proxy);
rawMap.set(proxy, initialVal);
return proxy;
}
function useReactive(initialState) {
let update = useUpdate();
let stateRef = useRef(initialState);
let state = useCreation(function () {
return observer(stateRef.current, function () {
update();
});
}, []);
return state;
}
export default useReactive;