Hooks 概览
Hooks 是在 React 组件中引入和管理状态和副作用的基本机制。
什么是 Hook ?
在前面的章节中,我们学到了 React 组件是基于特定 props 值的简单函数,用于表示 UI。为了使应用更可用,我们需要一种通过用户输入或向服务器发送请求来加载数据,从而交互式地操作 props 的方法。
这就是 Hook 的用武之地。Hook 是一种函数,它让我们可以为组件引入状态,并为不同的任务触发副作用,例如 HTTP 请求、直接访问 HTML DOM、获取窗口大小等等。
换句话说:Hook 可以让我们“钩入” React 特性。
示例: useState
Hook
让我们看一个例子,下面是一个 Counter
组件,它允许用户通过点击按钮来增加 count
值,并且新的 count
值会在按钮点击时被渲染:
// Counter.res
@react.component
let make = () => {
let (count, setCount) = React.useState(_ => 0);
let onClick = (_evt) => {
setCount(prev => prev + 1)
};
let msg = "You clicked" ++ Belt.Int.toString(count) ++ "times"
<div>
<p>{React.string(msg)}</p>
<button onClick> {React.string("Click me")} </button>
</div>
}
我们使用了 React.useState
Hook。我们在组件函数中调用它来为组件添加局部状态。React 会在重渲染之间保持这些状态。React.useState
返回一个元组,包括当前状态值(count
) 和一个更新状态值的函数(setCount
)。你能在处理事件时调用更新函数,或将更新函数传递给其他组件。
React.useState
的唯一参数是一个返回初始状态的函数(_ => 0
)。在上面的例子中,它是 0 ,因为我们的计数器从零开始。请注意,状态可以是任何类型,Rescript 会为你进行类型推断(只需要确保你的初始状态和你的类型匹配)。初始状态参数只会在首次渲染时使用。
这只是 Hook 的一个小例子。我们会在独立的 useState 章节中介绍更多细节。
可用的 Hooks
注意: 所有 Hooks 都在 React
模块下(例如 React.useState
)。
基础 Hooks:
useState: 为组件添加局部状态
useEffect: 在组件内运行有副作用的代码
useContext: 让你的组件能访问 React Context
额外 Hooks:
useReducer:
useState
的替代方案,使用state / action / reduce 模式useRef: 返回一个可变的 React Ref 值
Hooks 规则
Hooks 本质上是些简单函数,但是你需要在使用时遵循 两条规则。ReScript 不会在编译器中强制执行这些规则,如果你想要强制执行正确的 Hooks 约定,可以使用 eslint-plugin 来检查编译的 JS 输出。
1. 只在最顶层调用 Hook
不要在循环,条件或嵌套函数中调用 Hooks,确保总是在你的 React 函数的最顶层调用它们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState
和 useEffect
调用之间正确保持 Hooks 状态。(如果你对此感到好奇,ReactJS Hooks 文档 有更深入的解释。)
2. 只在 React 函数中调用 Hook
不要在普通的 JavaScript 函数中调用 Hook。 你可以:
✅ 在 React 的函数组件中调用 Hook
✅ 在自定义 Hook 中调用其他 Hook (我们将会在 自定义 hooks 章节中学习。)
遵循这些规则,确保组件的状态逻辑在代码中清晰可见。