用优雅的姿态走进 State 管理的世界 —— 详解 ahooks State 篇(二)
2024-01-11 01:59:56
引言
在前端开发中,状态管理是一个绕不开的话题。ahooks 作为一款优秀的 React Hooks 库,自然也提供了丰富的 State 管理工具。在本文中,我们将对 useMap、useSet、usePrevious、useRafState、useSafeState、useGetState、useResetState 这 7 个 Hook 的源码进行逐一解析,帮助你深刻理解其工作原理和使用方法。
正文
一、useMap
1. 简介
useMap Hook 可以让你轻松地将对象转换为 Map 结构,并自动处理 Map 的变化。它接受一个对象作为参数,返回一个 Map 对象和一个更新 Map 的函数。
2. 源码解析
export function useMap(initialValue) {
const mapRef = useRef(new Map(Object.entries(initialValue)));
const [, forceUpdate] = useState({});
const updateMap = useCallback((updater) => {
mapRef.current = updater(mapRef.current);
forceUpdate({});
}, []);
return [mapRef.current, updateMap];
}
useMap Hook 的实现原理很简单,它首先创建一个 useRef 引用,用于存储 Map 对象。然后使用 useState Hook 强制组件重新渲染,以便在 Map 发生变化时更新 UI。
updateMap 函数接受一个更新函数作为参数,该函数可以对 Map 进行修改。例如,你可以使用以下代码向 Map 中添加一个新的键值对:
updateMap((map) => {
map.set('newKey', 'newValue');
return map;
});
二、useSet
1. 简介
useSet Hook 与 useMap 类似,但它可以让你轻松地将对象转换为 Set 结构,并自动处理 Set 的变化。它接受一个数组作为参数,返回一个 Set 对象和一个更新 Set 的函数。
2. 源码解析
export function useSet(initialValue) {
const setRef = useRef(new Set(initialValue));
const [, forceUpdate] = useState({});
const updateSet = useCallback((updater) => {
setRef.current = updater(setRef.current);
forceUpdate({});
}, []);
return [setRef.current, updateSet];
}
useSet Hook 的实现原理与 useMap 类似,它首先创建一个 useRef 引用,用于存储 Set 对象。然后使用 useState Hook 强制组件重新渲染,以便在 Set 发生变化时更新 UI。
updateSet 函数接受一个更新函数作为参数,该函数可以对 Set 进行修改。例如,你可以使用以下代码向 Set 中添加一个新的值:
updateSet((set) => {
set.add('newValue');
return set;
});
三、usePrevious
1. 简介
usePrevious Hook 可以让你获取组件上一次渲染时的某个状态值。它接受一个值作为参数,返回该值的上次值。
2. 源码解析
export function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
usePrevious Hook 的实现原理很简单,它使用 useRef Hook 来存储组件上一次渲染时的值。然后在每次组件更新时,它都会将当前值赋给 useRef 引用。这样,你就可以在组件的任何地方获取到上一次渲染时的值。
例如,你可以使用以下代码获取组件上一次渲染时的计数器值:
const Counter = () => {
const [count, setCount] = useState(0);
const previousCount = usePrevious(count);
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
<p>Previous count: {previousCount}</p>
</div>
);
};
四、useRafState
1. 简介
useRafState Hook 可以让你在浏览器下一次重绘时更新状态。它接受一个更新函数作为参数,该函数可以对状态进行修改。
2. 源码解析
export function useRafState(initialState) {
const rafRef = useRef();
const [state, setState] = useState(initialState);
const setRafState = useCallback((updater) => {
cancelAnimationFrame(rafRef.current);
rafRef.current = requestAnimationFrame(() => {
setState(updater(state));
});
}, [state]);
useEffect(() => {
return () => cancelAnimationFrame(rafRef.current);
}, []);
return [state, setRafState];
}
useRafState Hook 的实现原理是利用浏览器