React Hook

什么是React Hook?

一个特殊的函数,用于钩入React的特性。

它鼓励我们将通用逻辑封装成Hook而不是工具函数,明确了通用工具函数和业务工具函数的边界。

使用React Hook有些什么好处?

1:很好的解决了状态逻辑复用难的问题,避免了嵌套地狱的出现。

2:关注点分离,代码逻辑更为清晰。

3:避免了class不能很好优化的问题,如不能很好的压缩,热重载不稳定。

使用React Hook规则有哪些?

1:只能在顶层使用,目的是保证Hook在每一次渲染中都能按照相同的顺序被调用。

2:只能在函数组件或者自义定Hook中调用。

React Hook是如何与组件关联起来的?

react会保持对当前渲染组件的追踪,每一个组件内部都有一个记忆单元格,用于存储JS对象数据。当你调用Hook时就读取当前Hook所在组件的记忆单元格里面的数据。

有哪些React Hook?

下边我们来一一整理下这些Hook的用法以及每个Hook应该注意的隐藏问题!

1:useState

概述:

让函数组件也可以维护自己的state。

用法:

const [state, setState] = useState(initialState);

setState()可以直接传递一个newState, 也可以传递一个函数,可获取前一状态的值。

如:setState((prevState) => {})

注意:

useState()不同于setState(), 它是状态替换而不是状态合并。

建议:

将独立的Sate拆分开来,为什么?

原因一:useState的state是替换,不是合并,所以拆分开来比较合理。

原因二:有助于关注点分离,相关功能逻辑在一起,代码清晰易观。

2:useEffect

概述:

它具有与componentDidMount、componentDidUpdate、componentWillUnmount三个生命周期钩子相同的用途,它是他们三者合并后的API。

用法:

useEffect(() => {}, 可选数组参数)

1:第一个参数为函数,该函数内部执行的动作相当于componentDidUpdate和componentDidUpdate两个生命周期中要干的事情,其结果返回一个函数,该函数内部定义的动作相当于componentWillUnmount生命周期时要干的事情 。但值得注意的是这个返回函数并不是在组件销毁时候执行的,事实上它会在我们每次重新渲染后被调用。为什么?因为useEffect的执行机制,每次我们重新渲染的时候都会生成新的effect用来替换掉之前的effect。所以某种意义上来说, effect更像是渲染结果的一部分,每一个effect属于一次特定的渲染。

2:第二个参数为可选参数,可能的值为空数组或者是具体依赖数组。其作用是优化重新渲染性能,相当于我们生命周期中shouldComponentUpdate对触发更新的依赖对象进行浅比较然后来确定是否需要重新渲染更新。

2-1:当省略这个参数的时候,相当于setState后都要进行更新。

2-2:当为[]时,只初始化执行一次,后边不再进行更新。

2-3:当为具体的依赖对象数组时,具体的依赖对象有变化就更新重渲染,没变化就不更新重渲染。

3:useContext

概述:

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。

它其实相当于class组件中 static context = xxTheme。我理解为是获取环境变量值的钩子。

当使用了该钩子函数的组件最近一层的<MyContext.Provider>更新时,该钩子会触发重新渲染。即使祖先使用了React.memo或者ShouldComponentUpdate,也会触发重新渲染。

用法:

cons xxTheme = useContext(xxContext);

const xxContext = React.createContext("xxx");

4:useLayoutEffect

概述:

其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

尽可能使用标准的 useEffect 以避免阻塞视觉更新。

5:useRef

概述:

它不仅可以用于DOM refs。它还是一个current属性可变且可以容纳任意值的通用容器,类似于class的实例属性。

用法:

const myRef = useRef(initialValue);

6:useCallback

概述:

把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。

抽离useEffect中的公共逻辑时很有用。

用法:

useCallback(fn, deps) 

7:useMemo

概述:

把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。

记住,传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo。

你可以把 useMemo 作为性能优化的手段,但不要把它当成语义上的保证。将来,React 可能会选择“遗忘”以前的一些 memoized 值,并在下次渲染时重新计算它们,比如为离屏组件释放内存。先编写在没有 useMemo 的情况下也可以执行的代码 —— 之后再在你的代码中添加 useMemo,以达到优化性能的目的。

用法:

useMemo(() => fn, deps)

8:useReducer

概述:

它其实是一个内置的自定义Hook。

当你有个相当复杂的组件包含了大量以特殊方式来管理的内部状态,我们通常会使用redux三方库来进行管理。但是如果此时你并不想引入三方库,那么自定义钩子函数useReducer就会是一个很不错的选择。

用法:

const [state, dispatch] = useReducer(reducer, initialArg, init);

具体实现参考官网自定义Hook

注意:

所谓惰性初始化,就是将用于计算state的逻辑抽取到reducer外部,这对未来重置state的action很有便利。

9:useImperativeHandle

概述:

在使用ref时自义定暴露给父组件的实例值。

它应当和forwardRef一起使用。

用法:

useImperativeHandle(ref, handle, [deps])

10:useDebugValue

概述:

useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签。

用法:

useDebugValue(value)

如: useDebugValue(isOnline ? "online" : "offline")

11: 自定义Hook

概述:

2个或更多组件间公用逻辑部分抽取封装成一个新的函数,函数名以use开始,内部可以调用其他Hook。

注意一:为什么要以use开头,这个约定主要是为了判断该函数内部是否使用了Hook调用,方便自动检查Hook调用是否符合规范。

注意二:两个或多个组件内部使用相同的自定义Hook不会共享state。自定义Hook只是一种重用状态逻辑的机制,从react的角度来看,我们的组件只是多次调用了useState和useEffect,它们是完全独立的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335