关于React中的钩子函数,我们已经非常熟悉了。钩子函数的功能非常的强大,而它的使用又十分简单。关于钩子函数的使用,我们只需记住两点:
- 钩子只能在React组件和自定义钩子中使用
- 钩子不能在嵌套函数或其他语句(if、switch、white、for等)中使用
React中自带的钩子函数
- useState
- useEffect
- useContext
- useReducer
- useCallback
- useRef
- useMemo
- useImperativeHandle
- useLayoutEffect
- useDebugValue(18.0新增)
- useDeferredValue(18.0新增)
- useTransition(18.0新增)
- useId(18.0新增)
- useSyncExternalStore(18.0新增)
- useInsertionEffect(18.0新增)
useMemo
useMemo和useCallback十分相似,useCallback用来缓存函数对象,useMemo用来缓存函数的执行结果。在组件中,会有一些函数具有十分的复杂的逻辑,执行速度比较慢。闭了避免这些执行速度慢的函数返回执行,可以通过useMemo来缓存它们的执行结果,像是这样:
const result = useMemo(()=>{ return 复杂逻辑函数(); },[依赖项])
useMemo中的函数会在依赖项发生变化时执行,注意!是执行,这点和useCallback不同,useCallback是创建。执行后返回执行结果,如果依赖项不发生变化,则一直会返回上次的结果,不会再执行函数。这样一来就避免复杂逻辑的重复执行。
useImperativeHandle
在React中可以通过forwardRef来指定要暴露给外部组件的ref:
const MyButton = forwardRef((props, ref) => {
return <button ref={ref}>自定义按钮</button>
});
上例中,MyButton组件将button的ref作为组件的ref向外部暴露,其他组件在使用MyButton时,就可以通过ref属性访问:
<MyButton ref={btnRef}/>
通过useImperativeHandle可以手动的指定ref要暴露的对象,比如可以修改MyButton组件如下:
const MyButton = forwardRef((props, ref) => {
useImperativeHandle(ref,()=> {
return {
name:'孙悟空'
};
});
return <button>自定义按钮</button>
});
useImperativeHandle的第二个参数是一个函数,函数的返回值会自动赋值给ref(current属性)。上例中,我们将返回值为{name:'孙悟空'}
,当然返回孙悟空没有什么意义。实际开发中,我们可以将一些操作方法定义到对象中,这样可以有效的减少组件对DOM对象的直接操作。
const MyButton = forwardRef((props, ref) => { const btnRef = useRef(); useImperativeHandle(ref,()=> { return { setDisabled(){ btnRef.current.disabled = true; } }; }); return <button ref={btnRef}>自定义按钮</button> }); const App = () => { const btnRef = useRef(); const clickHandler = () => { btnRef.current.setDisabled(); }; return <div> <MyButton ref={btnRef}/> <button onClick={clickHandler}>点击</button> </div>; };
useLayoutEffect
useLayoutEffect的方法签名和useEffect一样,功能也类似。不同点在于,useLayoutEffect的执行时机要早于useEffect,它会在DOM改变后调用。在老版本的React中它和useEffect的区别比较好演示,React18中,useEffect的运行方式有所变化,所以二者区别不好演示。
useLayoutEffect使用场景不多,实际开发中,在effect中需要修改元素样式,且使用useEffect会出现闪烁现象时可以使用useLayoutEffect进行替换。
useDebugValue
用来给自定义钩子设置标签,标签会在React开发工具中显示,用来调试自定义钩子,不常用。
useDeferredValue
useDeferredValue用来设置一个延迟的state,比如我们创建一个state,并使用useDeferredValue获取延迟值:
const [queryStr, setQueryStr] = useState('');
const deferredQueryStr = useDeferredValue(queryStr);
上边的代码中queryStr就是一个常规的state,deferredQueryStr就是queryStr的延迟值。设置延迟值后每次调用setState后都会触发两次组件的重新渲染。第一次时,deferredQueryStr的值是queryStr修改前的值,第二次才是修改后的值。换句话,延迟值相较于state来说总会慢一步更新。
延迟值可以用在这样一个场景,一个state需要在多个组件中使用。一个组件的渲染比较快,而另一个组件的渲染比较慢。这样我们可以为该state创建一个延迟值,渲染快的组件使用正常的state优先显示。渲染慢的组件使用延迟值,慢一步渲染。当然必须结合React.memo或useMemo才能真正的发挥出它的作用。
useTransition
当我们在组件中修改state时,会遇到复杂一些的state,当修改这些state时,甚至会阻塞到整个应用的运行,为了降低这种state的影响,React为我们提供了useTransition,通过useTransition可以降低setState的优先级。
useTransition会返回一个数组,数组中有两个元素,第一个元素是isPending,它是一个变量用来记录transition是否在执行中。第二个元素是startTransition,它是一个函数,可以将setState在其回调函数中调用,这样setState方法会被标记为transition并不会立即执行,而是在其他优先级更高的方法执行完毕,才会执行。
除了useTransition外,React还直接为为我们提供了一个startTransition函数,在不需要使用isPending时,可以直接使用startTransition也可以达到相同的效果。
useId
生成唯一id,使用于需要唯一id的场景,但不适用于列表的key。
催更啦,react项目啥时候上线啊,超哥
嗯
超哥,react视频下面链接只有前71集的代码