React中的钩子函数的功能非常的强大,而它的使用又十分简单。关于钩子函数的使用,我们只需记住两点:
1. 钩子只能在React组件和自定义钩子中使用 2. 钩子不能在嵌套函数或其他语句(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 TestButton = forwardRef((props, ref) => { return <button ref={ref}>Test</button> });
上例中,TestButton组件将button的ref作为组件的ref向外部暴露,其他组件在使用TestButton时,就可以通过ref属性访问:
<TestButton ref={btnRef}/>
通过useImperativeHandle可以手动的指定ref要暴露的对象,比如可以修改TestButton组件如下:
const TestButton = forwardRef((props, ref) => { useImperativeHandle(ref,()=> { return { name:'test-button' }; }); return <button>test</button> });
useImperativeHandle的第二个参数是一个函数,函数的返回值会自动赋值给ref(current属性)。上例中,我们将返回值为{name:'test-button'}
。实际开发中,我们可以将一些操作方法定义到对象中,这样可以有效的减少组件对DOM对象的直接操作。
const TestButton = forwardRef((props, ref) => { const btnRef = useRef(); useImperativeHandle(ref,()=> { return { setDisabled(){ btnRef.current.disabled = true; } }; }); return <button ref={btnRef}>Disable</button> }); const App = () => { const btnRef = useRef(); const clickHandler = () => { btnRef.current.setDisabled(); }; return <div> <TestButton ref={btnRef}/> <button onClick={clickHandler}>ok</button> </div>; };
UseLayoutEffect
useLayoutEffect的方法签名和useEffect一样,功能也类似。不同点在于,useLayoutEffect的执行时机要早于useEffect,它会在DOM改变后调用。在老版本的React中它和useEffect的区别比较好演示,React18中,useEffect的运行方式有所变化,所以二者区别不好演示。useLayoutEffect使用场景不多,实际开发中,在effect中需要修改元素样式,且使用useEffect会出现闪烁现象时可以使用useLayoutEffect进行替换。
UseDebugValue
用来给自定义钩子设置标签,标签会在React开发工具中显示,用来调试自定义钩子,不常用。
UseDeferredValue
useDeferredValue用来设置一个延迟的state,比如我们创建一个state,并使用useDeferredValue获取延迟值:
const [queryMember, setQueryMember] = useState(''); const deferredQueryMember = useDeferredValue(queryMember);
上边的代码中queryMember就是一个常规的state,deferredQueryMember就是queryMember的延迟值。设置延迟值后每次调用setState后都会触发两次组件的重新渲染。第一次时,deferredQueryMember的值是queryMember修改前的值,第二次才是修改后的值。换句话,延迟值相较于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。
标签:const,函数,钩子,React,hook,state,React18,组件,ref From: https://www.cnblogs.com/hlkawa/p/16747882.html