實現一個React hooks基礎狀態管理
const createContainer = (initialState) => {
let globalState = initialState;
const listeners = Object.fromEntries(Object.keys(initialState).map(key => [key, new Set()]));
const setGlobalState = (key, nextValue) => {
if (typeof nextValue === 'function') {
globalState = { ...globalState, [key]: nextValue(globalState[key]) };
} else {
globalState = { ...globalState, [key]: nextValue };
}
listeners[key].forEach(listener => listener());
};
const useGlobalState = (key) => {
const [state, setState] = useState(globalState[key]);
useEffect(() => {
const listener = () => {
setState(globalState[key]);
};
listeners[key].add(listener);
listener(); // in case it's already changed
return () => { listeners[key].delete(listener) }; // cleanup
}, []);
return [state, (nextValue) => setGlobalState(key, nextValue)];
};
return {
setGlobalState,
useGlobalState,
};
};
複製代碼
上述的 forceUpdate 爲
const useGlobalState = (key) => {
const [state, setState] = useState(globalState[key]);
useEffect(() => {
const listener = () => {
setState(globalState[key]);
};
listeners[key].add(listener);
listener(); // in case it's already changed
return () => { listeners[key].delete(listener) }; // cleanup
}, []);
return [state, (nextValue) => setGlobalState(key, nextValue)];
};
複製代碼
咱們能夠利用對象的不想等性質改寫forceUpdate 爲另一種形式
const useGlobalState = (key) => {
const [, forceUpdate] = useState({});
useEffect(() => {
const listener = () => {
forceUpdate({});
};
listeners[key].add(listener);
listener(); // in case it's already changed
return () => { listeners[key].delete(listener) }; // cleanup
}, []);
return [globalState[key], (nextValue) => setGlobalState(key, nextValue)];
};
複製代碼
咱們能夠利用自增數值改寫forceUpdate 爲另一種形式
const useGlobalState = (key) => {
const [, forceUpdate] = useState(0);
useEffect(() => {
const listener = () => {
forceUpdate(c => c + 1);
};
listeners[key].add(listener);
listener(); // in case it's already changed
return () => { listeners[key].delete(listener) }; // cleanup
}, []);
return [globalState[key], (nextValue) => setGlobalState(key, nextValue)];
};
複製代碼