使用库和框架可以让开发者更多地专注于开发,而工具会在后台处理某些功能。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 数据源,例如全局存储。