You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
在上面这个例子中,useState 就是一个 Hook,它接受一个参数作为 state 的初始值,返回一个数组,结构为 [value,setValue],其中 value 对应的 state,相当于 Class Component 中的 this.state,setValue 是修改 state 的函数,相当于 class Component 中 this.setState。 其他的就按照 Function Component 写就好了,是不是看起来很清爽?
functionCustomHookDemo(){const[hoverRef,isHover]=useHover();return<divref={hoverRef}>{isHover ? 'I am hovered' : 'I am not hovered'}</div>}//useHover 的 hookimportReact,{useState,useRef,useEffect}from'react';constuseHover=()=>{const[isHover,setIsHover]=useState(false)constref=useRef(null);consthandleMouseOver=()=>{setIsHover(true)}consthandleMouseOut=()=>{setIsHover(false)}useEffect(()=>{constnode=ref.current;if(node){node.addEventListener('mouseover',handleMouseOver);node.addEventListener('mouseout',handleMouseOut);return()=>{node.removeEventListener('mouseover',handleMouseOver);node.removeEventListener('mouseout',handleMouseOut);};}},[ref.current]);return[ref,isHover]}exportdefaultuseHover
React Hooks 尝鲜
前言
React 在 16.70-alpha 中首次提出 Hooks 这个新特性,并且在 16.8.0 正式发布 Hooks 稳定版本。React Hooks 指的是在 Function Component 中插入一些 Hooks,通过使用这些 Hooks 可以让 Function Component 拥有 state 和生命周期等 React 特性。
为什么会有 React Hooks
React Hooks 要解决的问题是状态逻辑复用,是继 render-props 和 higher-order components 之后的第三种状态共享方案。它主要解决了如下一些痛点:
组件中的状态逻辑难以复用
在一个 React Componet 中,会在 state 中存储状态,并且在组件的各个 lifecycle 函数中执行特有的逻辑,比如在 componentDidMount 去请求数据、在 componentWillUnMount 中卸载实例、取消事件监听器等。这些 state 和 生命周期和组件强耦合,使得 state 和生命函数的逻辑无法抽离得到复用。而 Hooks 可以从组件中提取状态逻辑,从而达到复用。
复杂组件导致的 wrapper hell 和逻辑难以维护
React 的组件带来的好处是模块化,但是当逻辑比较复杂时,就会出现组件嵌套地狱,看看 Devtool 里面的嵌套,是不是有点吓人。

除此之外,复杂组件会在不同的生命周期中执行很复杂的逻辑,比如在 componentDidMount 请求数据,或者在 componentWillReceiveProps 中根据 nextProps 改变组件 state 等等,后期维护和理解的成本会非常高。
再加上 class Component 的 this 指向问题,为了保证指向正确,需要用 bind 绑定或者使用箭头函数,如果没有绑定,就会出现各种 bug。
怎么用 React Hooks
首先使用 class Component 来实现一个最简单的组件:
在上面这个例子中,useState 就是一个 Hook,它接受一个参数作为 state 的初始值,返回一个数组,结构为 [value,setValue],其中 value 对应的 state,相当于 Class Component 中的 this.state,setValue 是修改 state 的函数,相当于 class Component 中 this.setState。 其他的就按照 Function Component 写就好了,是不是看起来很清爽?
API 介绍
现在介绍一下 React 内置的几种 Hooks 以及它们的用法。
useState
上面的例子就是用的 useState,当然是最简单的用法,总结一下 useState 的特性,如下:
useEffect
useEffect 是用来执行副作用操作的,通过这个 Hook,可以执行一些组件渲染之后的逻辑,比如事件监听、设置标题等。它相当于是 Class Component 中的 componentDidMount、componentDidUpdate、componentWillUnMount 这三个生命周期的集合。举个最简单的例子,如下:
这个 Hook 的特性如下:
useContext
useContext 主要是为了使用 context,而且不用像以前一样用 Provider、Consumer 包裹组件,可以大大提高代码的简洁性。使用 createContext 实现一个简单的例子,如下:
使用 context,就可以避免 props 的多层传递。对上面的例子使用 useContext 进行改造,代码如下:
使用 useContext 可以直接获取值,不需要用 ThemeContext.Consumer 包裹组件。代码看起来更加简洁。
useReducer
useReducer 主要是 useState 的语法糖,主要是针对复杂 state 或者下一个 state 依赖之前 state 的场景,主要有如下特点:
举个🌰如下:
如上例子所示,定义一个 reduce 函数,接收一个 state 和 action 参数,返回一个新的 state。通过传递 init 初始化函数,可以对 state 进行复位。
useCallback 和 useMemo
在 Class Component 中,我们可以使用 shouldComponentUpdate 来控制组件重新渲染的条件,从而避免复杂逻辑带来性能性能上的损耗,而在 Function Component 中没有 shouldComponentUpdate 这个生命周期,怎么办?useCallback 和 useMemo 就是用来解决这个问题的。
useCallback 和 useMemo 会在组件首次渲染的时候执行,然后会根据依赖项是否发生改变而再次执行,并且这两个 Hook 都返回缓存的值,useCallback 返回缓存的函数,useMemo 返回缓存的变量。
首先举一个🌰,如下:
如上所示:expensive 是计算量很大的函数,并且当 state 发生改变时,组件就会重新渲染,从而导致 computing 函数重新执行,而 computing 只和 count 相关,但是 value 发生改变,computing 还是会重新计算。这是没必要的,所以我们可以使用 useMemo 来控制没必要的执行,第二个参数表示依赖项,只有依赖项发生改变时才会执行。
useCallback 和 useMemo 不同的是,它返回一个缓存的函数,并且 useCallback(fn,deps) = useMemo(()=>fn(),deps),它有什么作用呢,举一个例子:
如上所示,父组件将 callback 函数传递给子组件,然后子组件在 useEffect 中判断 callback 是否发生改变,从而更新自身的 state,当父组件的 value state 发生改变是,并不会触发 useEffect 的更新操作,所以使用 useCallback 可以避免子组件不必要的重复渲染。
useRef
useRef 相当于是一个存储属性的地方,它在组件的整个生命周期内都保持不变,它的特性如下:
它的用法如下:
如上,在点击 button 时,设置 inputRef 获取焦点,其中 input 这个实例就保存在 inputRef 中。
useImperativeHandle
useImperativeHandle 用于自定义暴露给父组件的 ref 属性,该 hooks 需要和 forwardRef 一起使用,例子如下:
如上面所示,父组件可以直接调用在 Child 里面定义的 Ref.current.focus 方法。
useLayoutEffect
useLayoutEffect 和 useEffect 类似,两者不同的地方是:
useDebugValue
用户在 react devtools 中显示 hooks 属性,第二个参数可以进行格式化能力,例子如下:
自定义 Hooks
除了上面提到的官方已有的 hooks,我们还可以自定义 hooks,通过自定义,可以将组件逻辑提取到可重用的函数中。并且自定义的 hooks 之间也是相互独立的,举个例子:
如上所示,我们把 hover 的逻辑抽离到 useHover 这个 hook 中,并且把 hover 的 DOM 实例和 isHover 的值返回,这样其他组件想要这个逻辑就可以直接复用。
自定义 Hooks,需要遵循如下规则:
使用 Hooks 需要注意的点
虽然 Hooks 比较强大,但是在使用过程中,还是有一些点需要注意,比如:
The text was updated successfully, but these errors were encountered: