React Hook 是 v16.8 的新功能,自诞生以来,受到普遍的好评,在 React 版本更新中具备里程碑的意义。如今都2020年了,再不上车 React Hook 就真的 out 了...
javascript
本着“存在即合理”的原则,咱们先来康康 Hook 为咱们解决了哪些问题?Hook 有哪些优点呢?
在编写 React 组件时,咱们更喜欢函数组件,而不是 class 组件。
由于函数组件代码更少,结构更清晰,不容易产生 bug。可是,函数组件没办法使用状态,只能做为展现组件(就是个花瓶...哎)。
有了 Hook,咱们就能在函数组件中使用状态了**。绝不夸张的说,之后的组件均可以用函数组件 + Hook 来写。
class 组件的问题:html
componentDidMount
中注册事件以及其余的逻辑,在 componentWillUnmount
中卸载事件,这样分散不集中的写法,很容易写出 bug )
Hook 优点:java
ajax
请求、访问原生dom
元素、本地持久化缓存、绑定/解绑事件、添加订阅、设置定时器、记录日志等。以往这些反作用都是写在类组件生命周期函数中的。而 useEffect
在所有渲染完毕后才会执行,useLayoutEffect
会在浏览器 layout
以后,painting
以前执行Hook 可让你在不编写 class 组件的状况下使用 state 以及其余的 React 特性。可是,有些规则是咱们须要准守的:
react
useState
和 useEffect
调用之间保持 hook 状态的正确
ok,到此为止,咱们已经了解 Hook 有哪些优点了。
下面,咱们开始认识最经常使用的两个 Hook API—— useState、useEffect。
这两个API很好理解,并且很实用,弄懂能处理80%的业务场景。本文不会涉及太复杂的操做,仅仅做为入门。
git
先来看一段简单的 Hook 代码:github
import React, { useState } from 'react'; function Example() { // 声明一个叫 "count" 的 state 变量 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
咱们将经过将这段代码与一个等价的 class 示例进行比较来开始学习 Hook。面试
等价的 class 组件示例:ajax
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
很简单的一个加1计数器,Hook 写法比 class 组件是否是简洁了不少。
下面,咱们来分析如何使用 useState Hook...数组
// 第一步:从 react 库中引入 useState Hook import React, { useState } from 'react'; function Example() { /* 第二步:经过调用 useState Hook 声明了一个新的 state 变量。 * 它返回一对值(数组)解构到咱们命名的变量上。 * 第一个返回的是状态 count,它存储的是点击次数。咱们经过传 0 做为 useState 惟一的参数来将其初始化 0。 * 第二个返回的值自己就是一个函数。它让咱们能够更新 count 的值,因此咱们叫它 setCount。 */ const [count, setCount] = useState(0); // 声明一个叫 "count" 的 state 变量 return ( <div> // 第三步:读取 state,即count <p>You clicked {count} times</p> // 第四步:更新 state,经过 setCount() <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
经过上面的分析,咱们能够看到使用 useState Hook 管理状态简直太爽了。不用写繁琐的 class 组件,不用担忧 this 指向,代码是如此的清晰。
如何使用多个 state 变量:
将 state 变量声明为一对 [something, setSomething]
也很方便,由于若是咱们想使用多个 state 变量,它容许咱们给不一样的 state 变量取不一样的名称:浏览器
function ExampleWithManyStates() { // 声明多个 state 变量 const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: '学习 Hook' }]); ...
在以上组件中,咱们有局部变量 age
,fruit
和 todos
,而且咱们能够单独更新它们:
function handleOrangeClick() { // 和 this.setState({ fruit: 'orange' }) 相似 setFruit('orange'); }
你没必要使用多个 state 变量。State 变量能够很好地存储对象和数组,所以,你仍然能够将相关数据分为一组。然而,不像 class 中的 this.setState
,更新 state 变量老是_替换_它而不是合并它。
注意
你可能想知道:为何叫useState
而不叫createState
?
“Create” 可能不是很准确,由于state 只在组件首次渲染的时候被建立。在下一次从新渲染时,useState
返回给咱们当前的 state。不然它就不是 “state”了!这也是 Hook 的名字_老是_以use
开头的一个缘由。
Effect Hook定义:useEffect 传入一个 callback 函数
useEffect(effect: React.EffectCallback, deps?: ReadonlyArray<any> | undefined)
Effect Hook做用:处理函数组件中的反作用,如异步操做、延迟操做等,能够替代Class Component的componentDidMount
、componentDidUpdate
、componentWillUnmount
等生命周期。
Effect Hook特性:
ajax
请求、访问原生dom
元素、本地持久化缓存、绑定/解绑事件、添加订阅、设置定时器、记录日志等。componentDidMount
、componentDidUpdate
和 componentWillUnmount
具备相同的用途,只不过被合并成了一个 APIcomponentDidMount
或 componentDidUpdate
不一样,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快。大多数状况下,effect 不须要同步地执行。在个别状况下(例如测量布局),有单独的 useLayoutEffect Hook 供你使用,其 API 与 useEffect 相同
useEffect 使用示例:
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 相似 componentDidMount 和 componentDidUpdate useEffect(() => { // 使用浏览器 API 去更新 document 标题 document.title = `You clicked ${count} times`; }); // 相似 componentDidMount useEffect(() => { // 使用浏览器 API 去更新 document 标题 document.title = `You clicked ${count} times`; }, []); // 慎用!监听空数组,当 callback 使用到 state 或 props 时最好不要用,由于只能获取初始化的数据 // 返回一个函数用于清除操做 useEffect(() => { document.title = `You clicked ${count} times`; window.addEventListener('load', loadHandle); // loadHandle 函数定义省略 return () => { window.removeEventListener('load', loadHandle); // 执行清理:callback 下一次执行前调用 }; }, [count]); // 只有当count的值发生变化时,才会从新执行 callback return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
useEffect 用法很简单,可是有两个地方须要特别注意:
useEffect 的用法大概就是这样的,有一些坑和更复杂操做这里没有涉及。固然,要深刻理解的话须要去啃源码了,这里不作过多的解释。
Hook 核心知识点:闭包
当你在使用 Hook 遇到问题时,请先考虑是否因为闭包引发的。这将帮助你快速排查问题。
Hook 让咱们能够在函数组件中使用状态state,函数组件一统 React 的时代来了,这很棒。
Hook 可让咱们摒弃那些繁琐的生命周期、不用考虑 this 的指向、复用逻辑也不用写HOC了,这很棒。
Hook 还有更多 API 等着咱们去探索,同时也支持自定义 Hook。
Hook 发车啦,用过都说好...
参考:
Hook 官方文档
30分钟精通React Hooks
React Hooks彻底上手指南