解读 ahooks 源码系列 - Dev 篇
本篇文章是解读 ahooks@3.8.0 源码系列的第八篇 - Dev 篇,欢迎您的指正和点赞。
本文主要解读 useTrackedEffect、 useWhyDidYouUpdate 的源码实现。
useTrackedEffect
import { useRef, type DependencyList, useEffect } from "react";
type Effect<T extends DependencyList> = (
changes?: number[],
previousDeps?: T,
currentDeps?: T
) => void | (() => void);
const diffTwoDeps = (deps1?: DependencyList, deps2?: DependencyList) => {
// Let's do a reference equality check on 2 dependency list.
// If deps1 is defined, we iterate over deps1 and do comparison on each element with equivalent element from deps2
// As this func is used only in this hook, we assume 2 deps always have same length.
return deps1
? deps1
.map((_ele, idx) => (!Object.is(deps1[idx], deps2?.[idx]) ? idx : -1))
.filter((ele) => ele >= 0)
: deps2
? deps2.map((_ele, idx) => idx)
: [];
};
const useTrackedEffect = <T extends DependencyList>(
effect: Effect<T>,
deps?: [...T]
) => {
// 上一次的依赖
const previousDepsRef = useRef<T>();
useEffect(() => {
// 变化的依赖 index 数组
const changes = diffTwoDeps(previousDepsRef.current, deps);
const previousDeps = previousDepsRef.current;
previousDepsRef.current = deps;
return effect(changes, previousDeps, deps);
}, deps);
};
export default useTrackedEffect;
useWhyDidYouUpdate
import { useEffect, useRef } from "react";
export type IProps = Record<string, any>;
const useWhyDidYouUpdate = (componentName: string, props: IProps) => {
// 上一次的 props
const prevProps = useRef<IProps>({});
useEffect(() => {
if (prevProps.current) {
// 获取所有 key
const allKeys = Object.keys({ ...prevProps.current, ...props });
const changedProps: IProps = {};
allKeys.forEach((key) => {
// 哪些 key 进行了更新
if (!Object.is(prevProps.current[key], props[key])) {
changedProps[key] = {
from: prevProps.current[key],
to: props[key],
};
}
});
// 有 diff,控制台输出
if (Object.keys(changedProps).length) {
console.log("[why-did-you-update]", componentName, changedProps);
}
}
// 更新 prevProps
prevProps.current = props;
});
};
export default useWhyDidYouUpdate;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论