# 自定义 Hook 的创建与使用

URL: https://caijiao.org/react/chapter10/custom-hooks
Source: docs/react/chapter10/custom-hooks.md
Description: 自定义 Hook 是 React 中的一种机制，用于提取和复用组件逻辑。它可以将多个组件中共享的逻辑提取到独立的函数中，从而实现代码复用。

自定义 Hook 是一种在 React 中复用逻辑的强大方式。通过自定义 Hook，可以将组件中重复的逻辑提取到函数中，便于管理和复用。

## 1. 自定义 Hook 的创建

自定义 Hook 本质上是一个普通的 JavaScript 函数，它可以使用内置的 React Hook（如 `useState`、`useEffect`、`useReducer` 等）来管理状态或副作用。自定义 Hook 的名字通常以 `use` 开头，以便 React 能识别并遵循 Hook 的规则。

### 示例：使用自定义 Hook 管理表单输入

```jsx
import { useState } from 'react';

// 自定义 Hook：useInput
function useInput(initialValue) {
  const [value, setValue] = useState(initialValue);

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return {
    value,
    onChange: handleChange,
  };
}

// 使用自定义 Hook
function Form() {
  const name = useInput('');
  const email = useInput('');

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log('Name:', name.value);
    console.log('Email:', email.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" {...name} placeholder="Name" />
      <input type="email" {...email} placeholder="Email" />
      <button type="submit">Submit</button>
    </form>
  );
}
````

在上述代码中，`useInput` 是一个自定义 Hook，用来管理输入字段的状态。`Form` 组件通过调用 `useInput` 来获取表单字段的状态和事件处理器。

## 2. 自定义 Hook 的使用

自定义 Hook 的使用与普通 Hook 相似，它可以像其他 React Hook 一样在函数组件中调用。你可以将多个逻辑封装在自定义 Hook 中，进一步减少组件代码的复杂度。

### 示例：使用自定义 Hook 处理异步数据请求

```jsx
import { useState, useEffect } from 'react';

// 自定义 Hook：useFetch
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// 使用自定义 Hook
function DataDisplay({ url }) {
  const { data, loading, error } = useFetch(url);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
```

在这个示例中，`useFetch` 是一个自定义 Hook，用来处理数据获取的逻辑。`DataDisplay` 组件通过调用 `useFetch` 来请求数据并展示结果。

## 总结

自定义 Hook 是 React 中提高代码复用性和模块化的一种重要工具。通过将逻辑提取到自定义 Hook 中，可以避免在多个组件中重复相同的代码，提升代码的可维护性和可读性。
