学习 React 钩子 - 结合代码示例深入学习常见钩子

118 阅读4分钟

使用库和框架可以让开发者更多地专注于开发,而工具会在后台处理某些功能。React.js 是一个用于构建前端应用程序的流行 JavaScript 库。

在本文中,你将了解 React 的核心——钩子,以及钩子如何让Web开发者的开发工作变得更加轻松。

知识要求:

阅读本文,你除了需要了解 JavaScript 的基础知识。你还需要掌握 React 的基础知识,比如如何 React 设置应用程序、更新应用程序以及使用 React 状态。

入门介绍

如果你决定构建一个 React 应用程序——恭喜你!🎉 但当你深入了解 React钩子的世界后,你可能会感到不知所措。面对众多的 hooks,弄清楚何时使用哪些钩子可能有点令人头疼。

别担心——在本文中,我将逐一解析所有常用的钩子,让你清楚地知道如何协同使用各种常用的钩子。我们还会讨论哪些 hook 使用频率较高,哪些则相对较少。

读完本文后,你将对 React 钩子及其实际应用有一个全面的了解。

钩子是什么?

在 JavaScript 中,我们使用变量来存储数据,然后对存储的数据进行操作。

React 中的钩子也类似,但React 中的钩子专门用于在函数组件中管理状态。与手动声明一个变量不同,

像 useState 这样的钩子提供了一种声明带有状态值的状态变量,同时提供一个设置器函数来更新存储的状态。

以下是一个简单的钩子示例:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);  // Initialize state and state updater

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

在这段代码中,我使用 useState 钩子声明了一个名为 count 的状态,并将这个状态初始值设为 0。setCount 函数用于更新该状态。用户每次点击按钮时,我们使用 setCount 将 count 的值加 1。当状态更新时,React 会重新渲染组件以反映状态变化。

与直接声明 let count = 0 不同,使用 useState 状态让 React 能够在组件多次渲染之间记住状态,并确保正确更新 UI 。

React 钩子的类型

为了更容易理解,我们可以将 React 钩子分为八大类:

  • 状态管理钩子(State Management Hooks)——用于处理状态。
  • 副作用钩子(Effect Hooks)——用于处理副作用。
  • 引用钩子(Ref Hooks)——用于引用 JavaScript 值或 DOM 元素。
  • 性能优化钩子(Performance Hooks)——用于优化性能。
  • 上下文钩子(Context Hooks)——用于访问 React 上下文。
  • 过渡钩子(Transition Hooks)——用于提供更流畅的用户体验。
  • 特殊用途钩子(Some Random Hooks)——用于特殊用途的钩子。
  • 新钩子(React 19)——在最新 React 版本中引入的前沿工具。

在 React 中,你还可以根据不同的用例构建自定义钩子。每个钩子都以 use 关键字开头——即使是自定义钩子也遵循这种结构。这个关键字在 React 中是专门保留给钩子使用的。

接下来我们将详细探讨这些钩子。

状态管理钩子

1.useState

useState 钩子是 React 的钩子基础,也是最常用的钩子,也是管理函数组件状态的关键。通过 useState钩子,我们可以获取用户输入、显示或隐藏组件、以及管理数值,例如在电商应用中处理购物车数量。

useState 非常灵活且简单的:我们使用一个初始值来初始化它,它会返回一个状态变量和一个更新函数。

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);  //  初始化状态和状态更新器

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

**代码解释:**useState 初始化了状态(count),并提供了一个函数(setCount)来更新该状态。

2. useReducer

在 useState 钩子不能满足我们的需求时,useReducer 就派上用场了。这个钩子非常适合管理复杂的状态逻辑。

它使用一个 reducer 函数来简化状态更新,特别适合多个状态变量相互依赖或需要调度特定动作的情况。

可以将其视为管理更复杂状态场景的升级版 useState 钩子。以下是一个例子:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

代码解释:useReducer 对于管理复杂的状态更新非常有用,例如处理多个相关的操作。

3.useSyncExternalStore

useSyncExternalStore 是一个用于将非 React 状态存储集成到 React 组件中的钩子。

虽然useSyncExternalStore 不是常用的钩子,但如果你正在从头构建自己的状态管理库,这个钩子是至关重要的。

import React, { useSyncExternalStore } from 'react';

const externalStore = {
  subscribe: (callback) => {
    const interval = setInterval(callback, 1000);
    return () => clearInterval(interval);
  },
  getSnapshot: () => new Date().toLocaleTimeString(),
};

function Clock() {
  const time = useSyncExternalStore(externalStore.subscribe, externalStore.getSnapshot);
  return <div>{time}</div>;
}

**代码解释:**useSyncExternalStore 让我们能够将 React 组件连接到非 React 数据源,例如全局存储。

副作用钩子