import useRouteContext from '@docusaurus/useRouteContext';
import { DependencyList, useEffect, useRef, useState, useMemo } from 'react';
import { dequal } from 'dequal';
/* eslint-disable global-require */ // @ts-ignore
/**
* 用于深度检测依赖的useMemo钩子
* @param factory 返回值
* @param dependencies 依赖项
*/
export function useDeepCompareMemo<T>(factory: () => T, dependencies: DependencyList) {
return useMemo(factory, useDeepCompareMemoize(dependencies));
}
/**
* 深度检测依赖值是否改变
* @param deps 依赖项
*/
export const useDeepCompareMemoize = (deps: DependencyList) => {
const ref = useRef<DependencyList>([]);
if (!dequal(deps, ref.current)) {
ref.current = deps;
}
return ref.current;
};
/**
* 检测当页面属于哪个插件
* @param type
*/
export const usePluginCheck = (type: 'blog' | 'docs') => {
const [isBlog, setIsBlog] = useState<boolean>(false);
const context = useRouteContext();
useEffect(() => {
setIsBlog(context.plugin.name === `docusaurus-plugin-content-${type}`);
}, [context]);
return isBlog;
};
这段代码是使用 React 和 Docusaurus 编写的一些自定义钩子(Hook)。它们为React组件提供了一些特定功能,包括深度比较依赖项以及检测当前页面是由哪个Docusaurus插件生成的。
useDeepCompareMemo
和 useDeepCompareMemoize
useDeepCompareMemoize
是一个自定义的 React 钩子,它接受一个依赖项列表 deps
,然后使用 dequal 库来执行深度比较,检查依赖项是否已经改变。这是因为 React 自身的依赖项检查是基于浅层比较的,对于复杂的对象或数组,它可能无法正确地检测到变化。如果依赖项已经改变,那么 useDeepCompareMemoize
将更新 ref.current
的值。
useDeepCompareMemo
则是一个类似于 React 内置的 useMemo
钩子,但是它使用 useDeepCompareMemoize
来进行深度比较,而不是默认的浅层比较。这使得 useDeepCompareMemo
可以在复杂的依赖项发生变化时,正确地重新计算 factory
函数的值。
usePluginCheck
usePluginCheck
是一个自定义的 React 钩子,它接受一个字符串参数 type
,该参数应该是 'blog'
或 'docs'
。这个钩子检查当前页面是由哪个 Docusaurus 插件生成的。
这个钩子首先使用 useState
创建一个状态变量 isBlog
和它的更新函数 setIsBlog
。然后,它使用 useRouteContext
钩子获取当前路由的上下文。在 useEffect
钩子中,它将比较 context.plugin.name
和 docusaurus-plugin-content-${type}
。如果它们相等,那么 setIsBlog
将被调用,设置 isBlog
为 true
。usePluginCheck
钩子最后返回 isBlog
,表示当前页面是否由给定类型的插件生成。
这些自定义钩子为React组件提供了更复杂的功能,包括深度比较依赖项和检测页面的插件来源,这些都超出了React内置钩子的功能。这也显示了自定义钩子的强大能力,即为React组件添加任何你需要的功能。