React 新特性 React Hooks 的使用

Stella981
• 阅读 857

关注 前端技术专栏 ,回复“ 资源 ”免费领取全套视频教程

正文

什么是Hooks?

Hooks是React 16.8的新增特性。

它可以让你在不编写class的情况下使用state以及其他的React特性。

是一些可以让你在函数组件里“钩入” React state及生命周期等特性的函数。

Hook不能在class组件中使用,这使你不使用class也能使用React。

一个最简单的Hooks

首先我们来看一下,一个简单的有状态组件

class Example extends React.Component {

再来看一下使用hooks的版本

import { useState } from 'react';

两者对比会很清楚的发现,使用Hooks与不使用Hooks的区别,后者比前者是更简单的。可以看到, Example 是一个函数,但这个函数却拥有着自己的状态( count ),同时它还可以更新自己的状态( setCount )。这个函数能这样写,是因为它使用了Hooks的 useState 这个Hook,这个Hook让函数变成了一个有状态的函数。
除了 useState 这个Hook外,还有很多别的Hook,比如 useEffect 提供了类似于 componentDidMount 等生命周期钩子的功能, useContext 提供了上下文( context )的功能等等。
Hooks本质上就是一类特殊的函数,它们可以为你的函数型组件( function component )注入一些特殊的功能。

什么是useState?

useState是react自带的一个Hook函数,它的作用就是用来声明状态变量。useState这个函数接收的参数是我们的状态初始值(initial state),它返回了一个数组,这个数组的第 [0] 项是当前当前的状态值,第 [1] 项是可以改变状态值的方法函数。
所以就上方的例子我们做的事情其实就是,声明了一个状态变量count,把它的初始值设为0,同时提供了一个可以更改count的函数setCount。
下面来分解理解一下上方例子:

import React, { useState } from 'react';

调用useState方法的时候做了什么?

它定义一个 “state 变量”。我们的变量叫count,但是我们可以叫它任何名字,比如banana。这是一种在函数调用时保存变量的方式,useState是一种新方法,它与class里面的this.state提供的功能完全相同。一般来说,在函数退出后变量就会”消失”,而 state 中的变量会被React保留。

useState需要哪些参数?

useState() 方法里面唯一的参数就是初始state。不同于class的是,我们可以按照需要使用数字或字符串对其进行赋值,而不一定是对象。在示例中,只需使用数字来记录用户点击次数,所以我们传了0作为变量的初始 state。

useState方法的返回值是什么?

返回值为当前state以及更新state的函数。所以这就是我们写下方这段代码的原因。

const [count, setCount] = useState() 

这与class里面 this.state.count 和 this.setState 类似,唯一区别就是你需要成对的获取它们。

读取State

当在class中显示当前的 count ,是通过 this.state.count :

<p>You clicked {this.state.count} times</p>

在函数中,可以直接用 count :

<p>You clicked {count} times</p>

更新State

在class中,需要调用 this.setState() 来更新 count 值:

<button onClick={() => this.setState({ count: this.state.count + 1 })}>

在函数中,已经有了 setCount 和 count 变量,所以不需要this:

<button onClick={() => setCount(count + 1)}>

什么是Effect Hooks?

在上面的例子中增加一个新功能:

import { useState, useEffect } from 'react';

对比着看一下,如果没有hooks,应该怎么写?

class Example extends React.Component {

写的有状态组件,通常会产生很多的副作用(side effect),比如发起ajax请求获取数据,添加一些监听的绑定和取消绑定,手动修改dom等等。我们之前都把这些副作用的函数写在生命周期函数钩子里,比如componentDidMount,componentDidUpdate和componentWillUnmount。而现在的useEffect就相当与这些声明周期函数钩子的集合体。
同时,由于前文所说hooks可以反复多次使用,相互独立。所以我们合理的做法是,给每一个副作用一个单独的useEffect钩子。这样一来,这些副作用不再一股脑堆在生命周期钩子里,代码变得更加清晰。

useEffect做了什么?

通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。在这个 effect 中,我们设置了 document 的 title 属性,不过我们也可以执行数据获取或调用其他命令式的 API。

为什么在组件内部调用useEffect?

将useEffect放在组件内部让我们可以在effect中直接访问count state变量(或其他props)。我们不需要特殊的 API 来读取它,它已经保存在函数作用域中。Hook使用了JavaScript的闭包机制,而不用在JavaScript已经提供了解决方案的情况下,还引入特定的React API。

useEffect如何取消绑定一些副作用?

这种场景很常见,当我们在componentDidMount里添加了一个绑定,我们得马上在componentWillUnmount中,也就是组件被注销之前清除掉我们添加的绑定,否则内存泄漏的问题就出现了。

当不使用Hook useEffect的示例

class FriendStatus extends React.Component {

你会注意到 componentDidMount 和 componentWillUnmount 之间相互对应。使用生命周期函数迫使我们拆分这些逻辑代码,即使这两部分代码都作用于相同的副作用。

使用Hook useEffect的示例

import React, { useState, useEffect } from 'react';

这里有一个点需要重视!这种解绑的模式跟 componentWillUnmount 不一样。 componentWillUnmount 只会在组件被销毁前执行一次而已,而 useEffect 里的函数,每次组件渲染后都会执行一遍,包括副作用函数返回的这个清理函数也会重新执行一遍。

为什么要在effect中返回一个函数?

这是 effect 可选的清除机制。每个 effect 都可以返回一个清除函数。如此可以将添加和移除订阅的逻辑放在一起。

React何时清除effect?

React会在组件卸载的时候执行清除操作。正如之前学到的, effect 在每次渲染的时候都会执行。这就是为什么React会在执行当前 effect 之前对上一个 effect 进行清除。

为什么要让副作用函数每次组件更新都执行一遍?

先看以前的模式:

componentDidMount() {

很清楚,在 componentDidMount 绑定,再在 componentWillUnmount 取消绑定。但假如这时候 props.friend.id 变了怎么办?我们不得不再添加一个 componentDidUpdate 来处理这种情况:

componentDidUpdate(prevProps) {

看,很繁琐对吧。所以 useEffect 没这个问题,因为它在每次组件更新后都会重新执行一遍。

那如何跳过一些不必要的副作用函数呢?

按照上一节的思路,每次重新渲染都要执行一遍这些副作用函数,显然是不经济的。怎么跳过一些不必要的计算呢?我们只需要给 useEffect 传第二个参数即可。用第二个参数来告诉react只有当这个参数的值发生改变时,才执行我们传的副作用函数(第一个参数)。

useEffect(() => {

当第二个参数传一个空数组[]时,其实就相当于只在首次渲染的时候执行。也就是 componentDidMount 加 componentWillUnmount 的模式。不过这种用法可能会带来bug,建议少用。

如何自定义的Effect Hooks?

为什么要自己去写一个 Effect Hooks ? 因为这样我们才能把可以复用的逻辑抽离出来,变成一个个可以随意调用的代码块,哪个组件要用,就可以调用在哪个组件里!
比如我们可以把上面写的 FriendStatus 组件中判断朋友是否在线的功能抽出来,新建一个 useFriendStatus 的Hook专门用来判断某个id是否在线。

import { useState, useEffect } from 'react';

这时候 FriendStatus 组件就可以简写为:

function FriendStatus(props) {

这样抽离出来公共代码,就能够更加满足复用性。
假如这个时候我们又有一个朋友列表也需要显示是否在线的信息:

function FriendListItem(props) {

还有哪些自带的Effect Hooks?

除了上文重点介绍的 useState 和 useEffect ,react还给我们提供了很多有用的Hooks:

  • useContext

  • useReducer

  • useCallback

  • useMemo

  • useRef

  • useImperativeMethods

  • useMutationEffect

  • useLayoutEffect

这里,我就不再一一介绍了,大家可以自行查阅官方文档。

猜你爱看

手摸手带你分析记录那些年我们一起淌过的小程序坑

关于前端的工具你知道多少?别找了,都在这里。

看完尤雨溪直播聊Vue 3.0 beta不过瘾?再来看看文字版我做的整理吧

微  博:吴佳Jersey

QQ群:856363266


React 新特性 React Hooks 的使用

长按识别二维码

关注「前端技术专栏」加星标

每天给您推送最新原创技术文章

好看,帮点击在看❤️

本文分享自微信公众号 - 前端技术专栏(close_3245974231)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
海军 海军
3年前
React Hook丨用好这9个钩子,所向披靡
ReactHook指南什么是Hook?Hook是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。Hook本质上就是一个函数,它简洁了组件,有自己的状态管理,生命周期管理,状态共享。useStateuseEffectuseContextus
徐小夕 徐小夕
4年前
10分钟教你手写8个常用的自定义hooks
前言Hook是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。本文是一篇以实战为主的文章,主要讲解实际项目中如何使用hooks以及一些最佳实践,不会一步步再介绍一遍reacthooks的由来和基本使用,因为写hooks的文章很多,而且官网对于reacthooks的介绍也很详细
Souleigh ✨ Souleigh ✨
3年前
Hook 简介 – React
Hook简介_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。importReact,{useState}from'react';functionExample(){//声明一个新的叫做“count”的sta
Souleigh ✨ Souleigh ✨
3年前
Hook 规则 – React
Hook规则_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。Hook本质就是JavaScript函数,但是在使用它时需要遵循两条规则。我们提供了一个linter插件(https://www.npmjs.com/package/
亚瑟 亚瑟
3年前
自定义 Hook – React
自定义Hook_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。通过自定义Hook,可以将组件逻辑提取到可重用的函数中。在我们学习时,我们已经见过这个聊天程序中的组件,该组件用于显示好友的在线状态:importReact,{useSta
React Hooks源码深度解析
ReactHooks是React16.8引入的一个新特性,它允许函数组件中使用state和其他React特性,而不必使用类组件。Hooks是一个非常重要的概念,因为它们提供了更简单、更易于理解的React开发体验。本篇文章以ReactHooks源码为基,进行深度解析复盘其实现原理。
亚瑟 亚瑟
3年前
Hook API 索引 – React
HookAPI索引_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。本页面主要描述React中内置的HookAPI。如果你刚开始接触Hook,那么可能需要先查阅。你也可以在章节中获取有用的信息。基础Hook
亚瑟 亚瑟
3年前
使用 Effect Hook – React
使用EffectHook_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。_EffectHook_可以让你在函数组件中执行副作用操作importReact,{useState,useEffect}from'reac
亚瑟 亚瑟
3年前
使用 State Hook – React
使用StateHook_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。中使用下面的例子介绍了Hook:importReact,{useState}from'react';functionExample(){//
可莉 可莉
3年前
10分钟教你手写8个常用的自定义hooks
https://juejin.im/post/5e57d0dfe51d4526ce6147f2前言Hook是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。本文是一篇以实战为主的文章,主要讲解实际项目中如何使用hooks以及一些最佳实践,不会一步步再介