React钩子函数用法详解 – ReactJS实战教程

上一章ReactJS实战教程请查看:React使用上下文
hook钩子是React 16.8版本中引入的新特性,它允许你在不编写类的情况下使用state和其他React特性,hook是“hook into”的功能,它对功能组件的状态和生命周期特性做出反应,它在类中不起作用。
钩子是向后兼容的,这意味着它不包含任何中断更改。同时,它也不会取代你对React概念的认识。
何时使用钩子如果你编写了一个函数组件,然后想要向其添加一些状态,在此之前,你需要将其转换为一个类。但是,现在可以通过在现有的函数组件中使用一个钩子来实现。
钩子的规则钩子类似于JavaScript函数,但是在使用它们时需要遵循这两条规则。钩子规则确保组件中的所有有状态逻辑在其源代码中是可见的。这些规则是:
1.  只调用顶层的钩子
不要在循环、条件或嵌套函数中调用钩子。钩子应该总是在React函数的顶层使用。此规则确保在组件每次呈现时以相同的顺序调用挂钩。
2.  只从React函数调用钩子
不能从常规JavaScript函数调用钩子。相反,你可以从React函数组件调用钩子。钩子也可以从自定义钩子中调用。
React钩子的先决条件

  • 节点版本6或以上
  • NPM版本5.2或以上
  • 用于运行React应用程序的Create-react-app工具
React钩子安装要使用React hook,我们需要运行以下命令:
$ npm install react@16.8.0-alpha.1 --save $ npm install react-dom@16.8.0-alpha.1 --save

上面的命令将安装最新的React和支持React钩子的React- dom alpha版本,确保package.json文件列出如下所示,包含React和React-Dom依赖项。
"react": "^16.8.0-alpha.1", "react-dom": "^16.8.0-alpha.1",

钩子的状态Hook state是在React app中声明状态的一种新方法,Hook使用useState()函数组件来设置和检索状态,让我们通过下面的例子来理解Hook state。
App.js
import React, { useState } from 'react'; function CountApp() { // 声明一个新的状态变量,我们称之为count const [count, setCount] = useState(0); return ( < div> < p>You clicked {count} times< /p> < button onClick={() => setCount(count + 1)}> Click me < /button> < /div> ); } export default CountApp;

在上面的例子中,useState是一个钩子,它需要在一个函数组件中调用来添加一些本地状态。useState返回一个对,其中第一个元素是当前状态值/初始值,第二个元素是一个允许更新它的函数。之后,我们将从事件处理程序或其他地方调用此函数,useState的情况与此类似。在类上设置状态,没有钩子的等效代码如下所示。
App.js
import React, { useState } from 'react'; class CountApp extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( < div> < p>< b>你点击了 {this.state.count} 次< /b>< /p> < button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me < /button> < /div> ); } } export default CountApp;

钩子效果Effect Hook允许我们在函数组件中执行副作用(一个动作),它不使用类组件中可用的组件生命周期方法。换句话说,Effects钩子相当于componentDidMount()、componentDidUpdate()和componentWillUnmount()生命周期方法。
副作用具有大多数web应用程序需要执行的常见特性,例如:
  • 更新DOM,
  • 从服务器API获取和使用数据,
  • 建立订阅等。
让我们通过下面的例子来理解钩子效果。
import React, { useState, useEffect } from 'react'; function CounterExample() { const [count, setCount] = useState(0); // 类似于componentDidMount和componentDidUpdate: useEffect(() => { // 使用浏览器API更新文档标题 document.title = `You clicked ${count} times`; }); return ( < div> < p>你点击了 {count} 次< /p> < button onClick={() => setCount(count + 1)}> Click me < /button> < /div> ); } export default CounterExample;

上面的代码基于前面的示例,其中有一个新特性,我们将文档标题设置为自定义消息,包括单击次数。
在React组件中,有两种类型的副作用:
没有清理的效果
【React钩子函数用法详解 – ReactJS实战教程】清理的效果
没有清理的效果
它在useEffect中使用,它不会阻止浏览器更新屏幕。它使应用程序响应更快。最常见的不需要清理的影响是手动DOM突变、网络请求、日志记录等。
清理的效果
有些效果需要在DOM更新后清除,例如,如果我们想要设置对某个外部数据源的订阅,那么清理内存是很重要的,这样我们就不会引入内存泄漏。React在组件卸载时执行内存清理。然而,正如我们所知道的,效果对于每个渲染方法都是有效的,而不仅仅是一次。因此,在下一次运行特效之前,React也会清除之前渲染的效果。
自定义钩子自定义钩子是一个JavaScript函数。自定义钩子的名称以“use”开头,它可以调用其他钩子。自定义钩子就像一个常规函数,开头的单词“use”表示这个函数遵循钩子的规则。构建自定义钩子允许你将组件逻辑提取到可重用的函数中。
让我们在下面的示例中了解自定义钩子是如何工作的。
import React, { useState, useEffect } from 'react'; const useDocumentTitle = title => { useEffect(() => { document.title = title; }, [title]) }function CustomCounter() { const [count, setCount] = useState(0); const incrementCount = () => setCount(count + 1); useDocumentTitle(`You clicked ${count} times`); // useEffect(() => { //document.title = `你点击了 ${count} 次` // }); return ( < div> < p>You clicked {count} times< /p> < button onClick={incrementCount}>点击< /button> < /div> ) } export default CustomCounter;

在上面的代码片段中,useDocumentTitle是一个自定义钩子,它将参数作为一个文本字符串作为标题。在这个钩子中,我们调用useEffect钩子并设置标题,只要标题已经更改。第二个参数只在其本地状态与我们传入的不同时才执行检查和更新标题。
注意:自定义钩子是一种惯例,它自然地遵循钩子的设计,而不是一个React特性。
内置的钩子这里,我们将描述React中内置钩子的api。内置钩子可分为两部分,如下图所示。
基本的钩子
  • useState
  • useEffect
  • useContext
额外的钩子
  • useReducer
  • useCallback
  • useMemo
  • useRef
  • useImperativeHandle
  • useLayoutEffect
  • useDebugValue

    推荐阅读