Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >React Hooks 快速入门与开发体验(一)

React Hooks 快速入门与开发体验(一)

作者头像
贤羽
发布于 2022-06-09 07:14:19
发布于 2022-06-09 07:14:19
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

Vue 3 推出 Composition API 的时候,看到一些表示这和 React Hooks 很像的评论。

正好最近有个项目改用了 React 的,于是趁机体验了一下 React Hooks,看看是否真是如此。

简介

说来惭愧,上次使用 React,还是几年前想在 React 项目里想要实现组件样式作用域,对比和选择 css-modulesstyled-components 方案来着,最终实现体验还是不怎么样,后来大部分项目都是小程序、Vue 和 node.js 印象就还停留在那个年代。

那什么是 React Hook 呢?官方的介绍如下:

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。 (来源链接:https://zh-hans.reactjs.org/docs/hooks-custom.html

其中的 class 指的应该是 ES Class 也就是类语法,而 state 应该就是指平时通过 setState 更新状态来触发重渲染的组件 state 属性了。

并且官方保证它 没有破坏性改动

React Hook 是:

  • 完全可选的,可以轻松引入。如果你不喜欢,也可以不去学习和使用。
  • 100% 向后兼容,React Hook 不会包含任何破坏性改动。
  • 现在可用,Hook 已发布于 v16.8.0。

第一条说明官方并不强制要求使用 React Hook。第二条则是说明,使用它不会影响旧版代码,确保存量项目代码的正常工作。

至于支持 Hook 的 React 版本,大约发布于2018年底。到本文的2021年初算来,差不多已经过去两年时间了。

不过需要注意 React Hook 的使用规则:

  • 只能在 函数最外层 调用 Hook。
  • 只能在 React 的函数组件 中调用 Hook。

第二条很好理解,毕竟是为函数组件所设计的,第一条究竟为何,没有实际体验也很难说清楚,我们容后再叙。

既然已经出来两年之久,这个 React Hook 实际使用起来究竟效果如何呢?

一、基础 Hooks

1. useState

1-1. 基础示例

比如一个简单的点击计数示例,其中使用到一个计数 state,在每次点击后将其 +1 后更新视图:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { Component } from 'react';

class Example extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0,
        };
    }

    render () {
        const { count } = this.state;
        const setCount = (count) => this.setState({ count });

        return (
            <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
            </div>
        );
    }
}

如果使用 React Hooks 实现,就只需要这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { useState } from 'react';

function Example() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
}

这个例子中可以看出,React Hook 相比组件类:

  • 将组件从带有多个生命周期函数的类声明,直接简化为一个渲染函数的函数组件
  • 组件渲染时用到的属性和对应更新回调,通过一个名为 useState 的 Hook 来实现。
  • 对于组件类的生命周期函数,应该也可以通过其它 Hook 实现。

其它生命周期函数我们稍后再叙,先来看看一些上面的例子没有提到的情况:

1-2. 获取组件的 props

对于组件 props 的获取很简单,函数组件的第一个传入参数就是了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Child({ name }) {
    return (
        <p>Name: {name}</p>
    );
}

function Parent() {
    const children = [
        { id: 1, name: 'Adam' },
        { id: 2, name: 'Bernard' },
    ];

    return (
        <div>
            {children.map(({ id, name }) => (
                <Child key={id} name={name} />
            ))}
        </div>
    );
}
1-3. 更新数组/对象类型的 state

对于简单的值类型 state,直接使用 useState 返回的更新函数就可以轻松完成更新了。

对于数组和键值对(对象)类型的数据,又该怎么更新呢?

难道直接把整个新的数组/对象传入更新函数

——没错。

不过这样操作可能会稍显繁琐,因为必须传入一个新的数组/对象才能触发更新。直接修改原对象后直接传入更新函数的话,并不会触发重渲染。

所以我们需要创建一个数组/对象的拷贝,再传给更新函数,通常可以使用ES6数组方法和解构赋值对操作稍作简化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example() {
    const [list, setList] = useState([
        'hello world',
    ]);
    const add = () => {
        setList([...list, 'new item']);
    };
    const remove = (removeItem) => {
        setList(list.filter(item => item !== removeItem));
    };
    return (
        <div>
            {list.map((item, idx) => (
                <p key={idx}>
                    <span>{item}</span>
                    <button onClick={() => remove(item)}>
                        Remove
                    </button>
                </p>
            ))}
            <button onClick={add}>
                Add item
            </button>
        </div>
    );
}

但对于更复杂些的情况(比如对象数组),这样还是不太方便,不过也没关系后面会有处理这类情况的其它 Hook。

2. useEffect

2-1. 基础示例

使用 Hook 实现的函数组件(function component),其函数本身执行时机相当于 render 函数,执行较早。

对于日常开发中常用的其它生命周期,通常使用 useEffect Hook 实现。这里的 effect,官方称呼为“副作用”:

数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。不管你知不知道这些操作,或是“副作用”这个名字,应该都在组件中使用过它们。 (来源链接:https://zh-hans.reactjs.org/docs/hooks-effect.html

它的第一个参数是个回调函数,称之为 副作用函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example() {
    useEffect(() => {
        // 副作用执行
    });
}
2-2. 依赖数组

这样写的时候,副作用函数会在函数组件的每次 DOM 更新完毕后被调用,相当于类组件生命周期的 componentDidMount + componentDidUpdate

如果需要在其它时机执行副作用函数,就要靠第二个依赖数组字段了。

如果存在依赖数组,React 就会在每次副作用函数执行前,检查依赖数组中的内容。当依赖数组与上次触发时完全没有变化,就会掉过此次执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example({ name }) {
    const [count, setCount] = useState(0);
    useEffect(() => {
        // 当 count 更新时触发
    }, [count]);
    useEffect(() => {
        // 当 props.name 更新时触发
    }, [name]);
    useEffect(() => {
        // 当 count 或 props.name 更新时触发
    }, [count, name]);
}

依赖数组传空数组或者固定值的时候,每次触发的值都不会变化,所以这个副作用就只会在组件生命周期中执行一次。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example() {
    useEffect(() => {
        // 仅当组件创建挂载后触发一次
    }, []);
}

相当于类组件的 componentDidMount 生命周期函数。

2-3. 清理函数

对于副作用函数,我们还可以在其中返回一个对应的 清理函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example() {
    useEffect(() => {
        // 副作用执行
        return () => {
            // 副作用清理
        };
    }, []);
}

清理函数将在当前副作用函数失效、下一个副作用函数设定之前被执行。

上面的例子中,清理函数的执行时机相当于 componentWillUnmount

比如在组件挂载后添加一个对页面滚动做监听处理,并在卸载时清理监听器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example() {
    useEffect(() => {
        const onScroll = () => {
            // Do something.
        };
        window.addEventListener('scroll', onScroll);
        return () => {
            window.removeEventListener('scroll', onScroll);
        };
    }, []);
};
2-4. 改进

为什么要这样设计呢?官方给出了一个例子,就是根据 props 参数订阅数据源时,如果 props 参数发生变化,都需要清理旧订阅注册新订阅。

在类组件的实现中,这需要把对应处理分散在多个生命周期函数中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Example extends Component {    
    constructor(props) {
        super(props);
        this.onDataSourceChange = this.onDataSourceChange.bind(this);
    }

    componentDidMount() {
        DataSource.subscribe(
            this.props.dependId,
            this.onDataSourceChange,
        );
    }

    componentDidUpdate(prevProps) {
        DataSource.unsubscribe(
            prevProps.dependId,
            this.onDataSourceChange,
        );
        DataSource.subscribe(
            this.props.dependId,
            this.onDataSourceChange,
        );
    }

    componentWillUnmount() {
        DataSource.unsubscribe(
            this.props.dependId,
            this.onDataSourceChange,
        );
    }

    onDataSourceChange(status) {
        // Do something.
    }
}

可以看到,对于同一个数据源的处理被分散得七零八落,其中 componentDidUpdate 的处理还经常被遗忘,导致一些本不应该产生的 bug。

如果依赖于多个数据源的组件,或者还有其他相同生命周期的处理(如上面页面滚动事件的监听例子),还会让同一类数据源/事件的处理不能收拢到一起,反而因为发生时机而被混在其它不同数据源/事件的处理当中。导致组件编写过程中需要上下跳跃,而且后期维护中代码的阅读难度上升、可重构性下降

而通过 useEffect 实现,只需要放在同一个副作用处理内,再把相关参数放进依赖数组就行了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Example({ dependId }) {
    useEffect(() => {
        const onDataSourceChange = () => {
            // Do something.
        };
        DataSource.subscribe(dependId, onDataSourceChange);
        return () => {
            DataSource.unsubscribe(dependId, onDataSourceChange);
        };
    }, [dependId]);
};

只需要这样,不用再做 componentWillUpdate 的额外处理。而且最终同一类逻辑处理被收在同一个 effect 函数中,开发过程中聚焦单一问题,产出代码清晰可读,十分方便代码维护和重构。

可以说是非常方便了。

3. 小结

基础的 React Hook 就是上面的 useStateuseEffect 两个了,使用它们已经可以替代大部分以前使用类组件完成的功能,并且产出代码和执行效率都挺不错的。

简单概括一下对于 React Hook 的第一印象:

  • 用来实现更简洁的函数组件,代替类组件;
  • 没有破坏性改动;
  • 但有一定使用规则;
  • 用副作用机制代替组件生命周期函数;
  • 对于同一类逻辑处理,可以按照比组件更细的粒度进行收拢。

不过 React Hook 的设计也不是十全十美,有些问题通过简单例子可能无法体现出来,还需要通过更多使用场景的实践将其暴露出来。其它 Hooks 也将在新的例子中继续说明。

敬请期待~

To be continued.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-01-172,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
React Hooks 解析(上):基础
React Hooks 是从 v16.8 引入的又一开创性的新特性。第一次了解这项特性的时候,真的有一种豁然开朗,发现新大陆的感觉。我深深的为 React 团队天马行空的创造力和精益求精的钻研精神所折服。本文除了介绍具体的用法外,还会分析背后的逻辑和使用时候的注意事项,力求做到知其然也知其所以然。
Dickensl
2022/06/14
8010
React 新特性 React Hooks 的使用
是一些可以让你在函数组件里“钩入” React state及生命周期等特性的函数。
吴佳
2022/09/26
1.4K0
一文弄懂React 16.8 新特性React Hooks的使用
Hook是React 16.8的新增特性。 它可以让你在不编写class的情况下使用state以及其他的React特性。 是一些可以让你在函数组件里“勾入” React state及生命周期等特性的函数。 Hook不能在class组件中使用,这使你不使用class也能使用React。
吴佳
2022/09/26
1.8K0
React Hook实战
在React Hook出现之前的版本中,组件主要分为两种:函数式组件和类组件。其中,函数式组件通常只考虑负责UI的渲染,没有自身的状态也没有业务逻辑代码,是一个纯函数。而类组件则不同,类组件有自己的内部状态,界面的显示结果通常由props 和 state 决定,因此它也不再那么纯洁。函数式组件,类组件有如下一些缺点:
xiangzhihong
2020/12/21
2.1K0
React系列-轻松学会Hooks
❗️❗️HOC、Render Props 等基于组件组合的方案,相当于先把要复用的逻辑包装成组件,再利用组件复用机制实现逻辑复用。自然就受限于组件复用,因而出现扩展能力受限、Ref 隔断、Wrapper Hell……等问题
落落落洛克
2021/01/08
4.4K0
React系列-轻松学会Hooks
第七篇:React-Hooks 设计动机与工作模式(下)
经过第 6 课时的学习,相信你已经清楚了 React-Hooks 的来头,并理解了其背后的“设计动机”。本课时我们的任务是构建对 React-Hooks 的整体认知。
越陌度阡
2021/10/26
8960
30分钟精通React今年最劲爆的新特性——React Hooks
你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? ——拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function。
桃翁
2018/12/14
2K0
React Hooks 是什么
最近在重构 BadJS 的管理页面,使用 TypeScript + React Hooks 的技术栈,趁这个机会好好理一理 React Hooks 那些事儿。
李振
2021/11/26
3.3K0
React Hooks笔记:useState、useEffect和useLayoutEffect
useState 让函数组件也可以有 state 状态,并进行状态数据的读写操作。
德顺
2021/08/19
2.9K0
React Hooks 分享
        hooks: 钩子, React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来 。
子夜星辰
2022/11/15
2.3K0
React Hooks 分享
Hooks:尽享React特性 ,重塑开发体验
🎼 React 16.8 版本引入了 Hooks ,可以在不使用 Class 的情况下使用 React 特性。
奋飛
2024/05/25
1470
React Hooks 设计动机与工作模式
所谓类组件,就是基于 ES6 Class 这种写法,通过继承 React.Component 得来的 React 组件。以下是一个典型的类组件:
coder_koala
2021/05/28
1K0
React Hooks 设计动机与工作模式
react hooks api
hooks API是 React 16.8的"新增"功能(16.8更新于2年前)。官网是这么说的:
一粒小麦
2020/06/16
2.8K0
react hooks api
React 新特性 Suspense 和 Hooks
在去年的 React Conf 上,React 官方团队对 Suspense 和 Hooks 这两个未来版本中的新特性进行了介绍,随着 React v16 新版本的发布,这两个特性也逐步进入到了我们日常使用中,本文将对带你快速了解这两个新特性,以了解 React 的发展趋势及这些新特性对 React 编码方式的影响。
喂喂喂
2019/04/25
2.9K0
react hooks 全攻略
React Hooks 是 React 提供的一种功能,允许我们在函数组件中使用状态和其他 React 特性。使用 Hooks 可以简化函数组件中的状态管理和副作用处理。
程序员王天
2023/10/18
7600
React新特性全解(下)-- 一文读懂Hooks
我们知道,functional component在使用的时候有一些限制,比如需要生命周期、state的时候就不能用functional component。而有了Hooks,你就可以在funtional component里,使用class component的功能:props,state,context,refs,和生命周期函数等等。
前端迷
2019/07/12
1.1K0
React新特性全解(下)-- 一文读懂Hooks
React Hooks 中的属性详解
React Hooks 是 React 16.8 版本中新增的特性,允许我们在不编写 class 的情况下使用 state 和其他的 React 特性。Hooks 是一种可以让你在函数组件中“钩入” React 特性的函数。以下是一些常用的 React Hooks,并附有详细的用法和代码示例。
世间万物皆对象
2024/03/20
2280
React 16.8.6 升级指南(react-hooks篇)
从官方的态度可以很容易看出是十分重视hooks这个特性的,并且官方直言我们期望 Hook 能够成为人们编写 React 组件的主要方式。并且从笔者的实践过程来看hooks不仅仅是一种新玩法,更重要的意义是可以帮助开发者做减法,减少代码量,减少维护成本,甚至减少理解成本。
腾讯IVWEB团队
2020/06/28
2.8K0
理解 React Hooks
Sophie Alpert 和 Dan Abramov 在 React Conf 2018 中 提出了 hooks 这个概念,让我们一起来看看 Hooks 在解决一个什么问题。
志航
2018/11/04
5.4K0
理解 React Hooks
React核心 -- React-Hooks
第二个参数接收一个数组,用来表示需要追踪的变量,依赖列表,只有依赖更新的时候才会更新内容
小丞同学
2021/10/15
1.4K0
React核心 -- React-Hooks
相关推荐
React Hooks 解析(上):基础
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验