本篇文章是解读 ahooks@3.8.0 源码系列的第八篇 - Dev,欢迎您的指正和点赞。
本文主要解读 useTrackedEffect、 useWhyDidYouUpdate 的源码实现。
useTrackedEffect
文档地址
详细代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| 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
文档地址
详细代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| 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;
|