0


React -- State Hook 详细介绍(函数组件也可以使用state了)

Hook 简介

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

Hook 对 React 意味着什么?

  • 完全可选的。 你无需重写任何已有代码就可以在一些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使用 Hook
  • 100% 向后兼容的。 Hook 不包含任何破坏性改动
  • 现在可用。 Hook 已发布于 v16.8.0

没有计划从 React 中移除 class 。Hook 不会影响你对 React 概念的理解。 恰恰相反,Hook 为已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命周期。

Hook 的使用动机是什么?

在使用 React 中,或许会遇见过以下的窘境

1、在组件之间复用状态逻辑很难

React 没有提供将可复用性行为“附加”到组件的途径(例如,把组件连接到 store)。render props 和 高阶组件 或许可以解决此类问题,但是这类方案需要重新组织组件结构,这可能会很麻烦,使代码难以理解。由 providers,consumers,高阶组件,render props 等其他抽象层组成的组件会形成“嵌套地狱”。

可以使用 Hook 从组件中提取状态逻辑,使得这些逻辑可以单独测试并复用。Hook 使你在无需修改组件结构的情况下复用状态逻辑。 这使得在组件间或社区内共享 Hook 变得更便捷。

2、复杂组件变得难以理解

组件起初很简单,但是逐渐会被状态逻辑和副作用充斥。每个生命周期常常包含一些不相关的逻辑。例如,组件常常在

componentDidMount

componentDidUpdate

中获取数据。但是,同一个

componentDidMount

中可能也包含很多其它的逻辑,如设置事件监听,而之后需在

componentWillUnmount

中清除。相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。

在多数情况下,不可能将组件拆分为更小的粒度,因为状态逻辑无处不在。这也给测试带来了一定挑战。同时,这也是很多人将 React 与状态管理库结合使用的原因之一。但是,这往往会引入了很多抽象概念,需要你在不同的文件之间来回切换,使得复用变得更加困难。

为了解决这个问题,Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分,可以使用 reducer 来管理组件的内部状态,使其更加可预测。

3、难以理解的 class

除了代码复用和代码管理会遇到困难外,学习class 是 React 的一大屏障,理解 JavaScript 中

this

的工作方式,与其他语言存在巨大差异。还不能忘记绑定事件处理器。没有稳定的语法提案,这些代码非常冗余,或许你理解 props,state 和自顶向下的数据流,但对 class 却一筹莫展。

使用 class 组件会无意中鼓励开发者使用一些让优化措施无效的方案。class 也给目前的工具带来了一些问题。例如,class 不能很好的压缩,并且会使热重载出现不稳定的情况。

为了解决这些问题,Hook 使你在非 class 的情况下可以使用更多的 React 特性。 从概念上讲,React 组件一直更像是函数。而 Hook 则拥抱了函数,同时也没有牺牲 React 的精神原则。Hook 提供了问题的解决方案,无需学习复杂的函数式或响应式编程技术。

以上就是 React Hook 的一些简要介绍,接下来详细介绍 Hook 的其中之一:State Hook。

State Hook

基本例子

如下例子,在 React 中,使用 class 的方式创建一个计时器

class Count 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>
    );
  }
}

state 初始值为

{ count: 0 }

,当用户点击按钮后,我们通过调用

this.setState()

来增加

state.count

之前,我们在创建具有状态的组件时,使用的是 class 的方式;而 Hook 可以另函数组件拥有更多的 React 特性,如 state 。使用 Hook 改写上面的 class 组件创建方式

import React, { useState } from 'react';

function Count() {
  // 声明一个叫 "count" 的 state 变量
  const [count, setCount] = useState(0);

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

Hook 和 函数组件

React 的函数组件

const Count = (props) => {
  // 你可以在这使用 Hook
  return <div />;
}

或是这样

function Count(props) {
  // 你可以在这使用 Hook
  return <div />;
}

之前可能把它们叫做“无状态组件”,但现在为它们引入了使用 React state 的能力,所以更喜欢称之为”函数组件”。

看到这里,此处 Hook 到底是什么?

Hook 是什么?

在上面的示例中,引入 React 中

useState

的 Hook

import React, { useState } from 'react';

function Count() {
  // ...
}

Hook 是一个特殊的函数,它可以让你“钩入” React 的特性。例如,

useState

是允许你在 React 函数组件中添加 state 的 Hook。 如果在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其它转化为 class,现在可以在现有的函数组件中使用 Hook。

声明 State

使用 class 方式,在构造函数中设置

this.state

{ count: 0 }

来初始化

count

state 为

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

在函数组件中,没有

this

,所以不能分配或读取

this.state

。我们直接在组件中调用

useState

Hook

import React, { useState } from 'react';

function Count() {
  // 声明一个叫 “count” 的 state 变量
  const [count, setCount] = useState(0);
}

useState

调用

它定义一个 “state 变量”。我们的变量叫

count

, 但是我们可以叫他任何名字,比如

banana

。这是一种在函数调用时保存变量的方式 ——

useState

是一种新方法,它与 class 里面的

this.state

提供的功能完全相同。一般来说,在函数退出后变量就会“消失”,而 state 中的变量会被 React 保留。

useState

参数

useState()

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

0

作为变量的初始 state。(如果我们想要在 state 中存储两个不同的变量,只需调用

useState()

两次即可。)

useState

返回值

返回值为当前 state 以及更新 state 的函数。这就是我们写

const [count, setCount] = useState()

的原因。这与 class 里面

this.state.count

this.setState

类似,唯一区别就是你需要成对的获取它们。

重看以下例子

import React, { useState } from 'react';

function Count() {
  // 声明一个叫 "count" 的 state 变量
  const [count, setCount] = useState(0);
}

声明了一个叫

count

的 state 变量,然后把它设为

0

。React 会在重复渲染时记住它当前的值,并且提供最新的值给我们的函数。我们可以通过调用

setCount

来更新当前的

count

读取 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 })}>
  Click me
</button>

在函数中,我们使用

setCount

更新

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

示例分析

步骤分析

// 引入 React 中的 useState Hook。它让我们在函数组件中存储内部 state。
import React, { useState } from 'react';

function Count() {
  // 在 Count 组件内部,我们通过调用 useState Hook 声明了一个新的 state 变量。
  // 它返回一对值给到我们命名的变量上。我们把变量命名为 count,因为它存储的是点击次数。
  // 我们通过传 0 作为 useState 唯一的参数来将其初始化为 0。第二个返回的值本身就是一个函数。
  // 它让我们可以更新 count 的值,所以我们叫它 setCount。
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <!-- 当用户点击按钮后,我们传递一个新的值给 setCount。React 会重新渲染 Count 组件,并把最新的 count 传给它。 -->
      <button onClick={() => setCount(count + 1)}>
       Click me
      </button>
    </div>
  );
}

方括号的作用

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

以上是 JavaScript 语法叫数组解构。它意味着我们同时创建了 count 和

setCount

两个变量,count 的值为

useState

返回的第一个值,

setCount

是返回的第二个值。它等价于下面的代码

const countStateVariable = useState(0);   // 返回一个有两个元素的数组
const count = countStateVariable[0];   // 数组里的第一个值
const setCount = countStateVariable[1];   // 数组里的第二个值

当我们使用

useState

定义 state 变量时候,它返回一个有两个值的数组。第一个值是当前的 state,第二个值是更新 state 的函数。使用

[0]

[1]

来访问有点令人困惑,因为它们有特定的含义。这就是我们使用数组解构的原因。

使用多个 state 变量

将 state 变量声明为一对

[something, setSomething]

也很方便,因为如果我们想使用多个 state 变量,它允许我们给不同的 state 变量取不同的名称

function ManyStates() {
  // 声明多个 state 变量
  const [age, setAge] = useState(18);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: '学习 Hook' }]);
}

在以上组件中,我们有局部变量

age

fruit

todos

,并且我们可以单独更新它们

function handleAgeClick() {
  // 和 this.setState({ age: 19 }) 类似
  setAge(19);
}

总结

以上内容中,我们了解了 React 提供的

useState

Hook,有时候我们也叫它 “State Hook”。它让我们在 React 函数组件上添加内部 state 。

我们还学到了什么是 Hook。Hook 是能让你在函数组件中“钩入” React 特性的函数。它们名字通常都以

use

开始,不妨试试在项目中使用。

(更多前端相关博客请查看我的主页喔~~~关注我,一起学前端,共同进步)


本文转载自: https://blog.csdn.net/qq_41809113/article/details/122500836
版权归原作者 前端不释卷leo 所有, 如有侵权,请联系我们删除。

“React -- State Hook 详细介绍(函数组件也可以使用state了)”的评论:

还没有评论