React Hook
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Hook相关的知识,希望对你有一定的参考价值。
参考技术Areact 16.8 以后加上了 react hook,它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。16.8之前,react组件可以分为类组件和函数组件。
我们为什么要拥抱react hook?由于类组件存在以下几点问题:
下面逐一介绍官方提供的hook API。
1.useState()
作用:返回一个状态以及能修改这个状态的setter,在其他语言称为元组(tuple),一旦mount之后只能通过这个setter修改这个状态。
2.useEffect(callback, arr)
作用:处理函数组件中的副作用,如异步操作、延迟操作等。useEffect有两个参数,callback和数组依赖项,无arr时相当于componentDidMount生命周期,有arr时相当componentDidMount和componentDidUpdata生命周期。如果callback中有return,则相当于componentWillUnmount。
3.useContext
作用:跨组件共享数据钩子,使用可分为三步:
4.useReducer
作用:用于管理复杂的数据结构(useState一般用于管理扁平结构的状态),基本实现了redux的核心功能。 useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
5.useMemo、useCallback
这俩个Api与性能优化有关。react中,性能的优化点在于:
基于上面的两点,我们通常的解决方案是:使用immutable进行比较,在不相等的时候调用setState;在shouldComponentUpdate中判断前后的props和state,如果没有变化,则返回false来阻止更新。
在hooks出来之后,我们能够使用function的形式来创建包含内部state的组件。但是,使用function的形式,失去了上面的shouldComponentUpdate,我们无法通过判断前后状态来决定是否更新。而且,在函数组件中,react不再区分mount和update两个状态,这意味着函数组件的每一次调用都会执行其内部的所有逻辑,那么会带来较大的性能损耗。因此useMemo 和useCallback就是解决性能问题的杀手锏。
useCallback和useMemo的参数跟useEffect一致。useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。
通过一个例子来看useMemo的作用:
不使用useMemo,无论count还是val改变都会执行expensive()
使用useMemo,只有在count发生改变使才会会执行expensive()
useCallback跟useMemo比较类似,但是使用场景不同:比如有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。
6.useRef
useRef是一个方法,返回一个可变的 ref 对象;其 .current 属性被初始化为传入的参数(initialValue);可以保存任何类型的值:dom、对象等任何可变值;返回的 ref 对象在组件的整个生命周期内保持不变;修改 ref 的值是不会引发组件的重新 render 。
useRef非常常用的一个操作,访问DOM节点,对DOM进行操作,监听事件等等,如下:
除了传统的用法之外,它还可以“跨渲染周期”保存数据。
在上面的例子中,点击了 打印like 按钮后,连续点击数字按钮,会发现2s后 likeRef.current 打印出11,而 like 打印出1。
因为,在任意一次渲染中,props和 state 是始终保持不变的,如果props和state在任意不同渲染中是相互独立的话,那么使用到他们的任何值也是独立的。所以onButtonClick时拿到的时未点击数字按钮时的 like 值。
而ref 在所有 render 都保持着唯一的引用,因此所有的对 ref 的赋值或者取值拿到的都是一个 最终 的状态,而不会存在隔离。
7.useImperativeHandle
当userRef用于一个组件时,useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值;如果不使用,父组件的ref(chidlRef)访问不到任何值(childRef.current==null);且 useImperativeHandle 应当与 forwardRef 一起使用。
8.useLayoutEffect
用法与useEffect 相同,但它会在所有的 DOM 变更之后同步调用(立即执行)。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。由于会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制。
使用场景:当useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现闪屏问题。
9.useDebugValue
useDebugValue 用于在 React 开发者工具中显示 自定义 Hook 的标签。
useDebugValue 接受一个格式化函数作为可选的第二个参数。该函数只有在 Hook 被检查时才会被调用。它接受 debug 值作为参数,并且会返回一个格式化的显示值。
以上是关于React Hook的主要内容,如果未能解决你的问题,请参考以下文章