乐趣区

react hooks 全面转换攻略(二) react本篇剩余 api

useCallback,useMemo
因为这两个 api 的作用是一样的, 所以我放在一起讲;
语法:
function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T;
function useCallback<T extends (…args: any[]) => any>(callback: T, deps: DependencyList): T;
区别在于第一个参数, 还有参数的传递, 另外 useCallback 中 DependencyList 是一个必须值
这两个 api 的作用基本就是缓存数据 / 方法
使用过 react 的人都知道, 在组件传递值的时候, 如果 props 中某一值对象引用发生变化, 就会发生重新渲染, 即使前后 2 个对象是完全相同的;
这 2 个参数就是为了解决这个问题, 另外也有可以减轻一些方法的 rerender 的速度;

useRef
作用基本是取代 class 中的 createRef, 在此不多细说

useContext
作用基本是取代 class 中的 Context 中 Context.Provider , 接受参数 Context, 因为可能会有多层 context, 所以这个参数是必须的, 不然无法辨别

useImperativeHandle
语法:
function useImperativeHandle<T, R extends T>(ref: Ref<T>|undefined, init: () => R, deps?: DependencyList): void;
官网是叫 useImperativeMethods, 但是我在 @types/react@17.8.7 中, 是叫做 useImperativeHandle 的, 不过函数名还是以实际为准
在官网中, 他的作用是这样解释的:
useImperativeMethods 自定义使用 ref 时公开给父组件的实例值。与往常一样,在大多数情况下应避免使用 refs 的命令式代码。
这个 api 的使用必定伴随着 forwardRef 这个 api, 使用率基本较低;
官方例子:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeMethods(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} />;
}
FancyInput = forwardRef(FancyInput);
在此示例中,呈现 <FancyInput ref = {fancyInputRef} /> 的父组件将能够调用 fancyInputRef.current.focus()。
简单的说就是讲子组件中的创建方法暴露给父组件

useMutationEffect
签名与 useEffect 相同,但在更新兄弟组件之前,它在 React 执行其 DOM 突变的同一阶段同步触发。使用它来执行自定义 DOM 突变。
同样的 @types/react@16.8.7 没有这个函数的声明; 不过官网中 大多是告诫尽量少用此函数

useLayoutEffect
语法:
function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void;
参数基本和 useEffect 相同
官方所说的效果:
签名与 useEffect 相同,但在所有 DOM 突变后它会同步触发。使用它从 DOM 读取布局并同步重新渲染。在浏览器有机会绘制之前,将在 useLayoutEffect 内部计划的更新将同步刷新。
不知道大家有没有使用过 vue, 他的作用和 vue 中的 nexttick 差不多吧; 在需要读取 dom 的高度, 宽度的时候特别需要

说到现在, api 基本已经讲完了, 除了 useReducer, 我将会放在 redux 篇中讲述

退出移动版