My App

Hooks 规则

Hooks 规则

所以,我们已经讨论过钩子是允许我们“钩入”React 内部的特殊函数。 useState 允许我们连接到组件实例的状态,例如,而 useId 允许我们在组件实例上创建并存储一个唯一标识符。

如果我们尝试在 React 上下文之外调用这些函数,会发生什么?

好吧,我们试试看:

import React from 'react';

try {
  React.useId();
} catch (err) {
  // Swallowing an error that occurs because
  // of the warning shown in the console.
}

除了 lint 错误,我们还收到了一个看起来像这样的控制台消息:

警告:无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:

  1. 您可能有不匹配的 React 和渲染器(例如 React DOM)版本
  2. 您可能正在违反 Hooks 规则
  3. 你可能在同一个应用中有多个 React 副本

这表明出现了严重的问题,并提供了三种可能性。错误 1 和错误 3 涉及罕见的边缘案例问题,但第二个要点很有趣。“Hooks 的规则”是什么?

首先,让我们明白,hooks 就是普通的 JavaScript 函数。它们并不像看起来那么神奇。

但是,当我们调用这些函数时,它们会“钩入”React 内部。我们可以让 React 措手不及。它期望这些钩子函数以非常特定的方式使用,如果我们违反这些期望,就会发生坏事。

我们应该了解两个“钩子规则”,以确保我们始终按照 React 的预期使用钩子。

  1. Hooks 必须在 React 应用程序的范围内调用。我们不能在 React 组件之外调用它们。*
  2. 我们必须在组件的顶层调用我们的钩子。

第二条规则是让大多数人感到困惑的那条。我们来谈谈它。

这是视频中的沙盒:

import React from 'react';

import TextInput from './TextInput';

function App() {
  return (
    <>
      <TextInput label="Name" />
      <TextInput
        id="my-email"
        label="Email"
        type="email"
      />
    </>
  );
}

export default App;

缺少了什么

在这个例子中,我们的 TextInput 组件缺少一些非常重要的属性: value 和 onChange 。没有这些属性,就无法使用 React 状态驱动这个组件。

我没有包括它们,因为它们与本课无关,但如果你想在你的应用中使用受控输入,它们是非常重要的!

这是一个更完整的实现:

function TextInput({ id, label, type, value, onChange }) {
  let generatedId = React.useId();
  let appliedId = id || generatedId;
 
  return (
    <div className="text-input">
      <label htmlFor={appliedId}>{label}</label>
      <input id={appliedId} type={type} value={value} onChange={onChange} />
    </div>
  );
}

在本课程的后面,我们将学习如何在这种情况下自动委派 props。