返回

React Hook 实战指南(四) - 钩子函数的妙用

前端

React Hook 是 React 16.8 版本引入的全新特性,它彻底改变了函数组件的编写方式,让开发者能够以更简洁、更具表现力的方式编写 React 组件。在之前的文章中,我们已经介绍了一些常用的 Hook,如 useState、useEffect 和 useCallback。在本文中,我们将继续探索更多 React Hook 在业务中的使用,带你领略 Hook 函数的强大魅力。

useEffect Hook 的进阶用法

useEffect Hook 是 React Hook 中最强大的 Hook 之一,它允许我们在组件的生命周期中执行副作用操作,例如获取数据、设置定时器或更新 DOM。在上一篇文章中,我们已经介绍了 useEffect Hook 的基本用法,但它还有更多高级用法值得探索。

1. useEffect Hook 的多个依赖项

useEffect Hook 可以接受第二个参数,即依赖项数组。如果依赖项数组中的任何一项发生变化,useEffect Hook 就会再次执行。这可以让我们只在必要时执行副作用操作,从而提高性能。

例如,假设我们有一个组件,它需要在每次重新渲染时从服务器获取数据。我们可以使用 useEffect Hook 来实现这个功能,如下所示:

import { useEffect, useState } from "react";

const MyComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch("/api/data");
      const data = await response.json();
      setData(data);
    };

    fetchData();
  }, []);

  return (
    <div>
      {data ? <div>{data.message}</div> : <div>Loading...</div>}
    </div>
  );
};

export default MyComponent;

在这个例子中,useEffect Hook 的第二个参数是一个空数组。这意味着 useEffect Hook 只会在组件第一次渲染时执行一次。如果我们希望 useEffect Hook 在每次重新渲染时都执行,我们可以将第二个参数改为一个包含所有组件状态变量的数组,如下所示:

import { useEffect, useState } from "react";

const MyComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch("/api/data");
      const data = await response.json();
      setData(data);
    };

    fetchData();
  }, [data]);

  return (
    <div>
      {data ? <div>{data.message}</div> : <div>Loading...</div>}
    </div>
  );
};

export default MyComponent;

这样,只要 data 状态变量发生变化,useEffect Hook 就会再次执行,并从服务器获取最新数据。

2. useEffect Hook 的清理函数

useEffect Hook 还可以接受一个第三个参数,即清理函数。清理函数会在组件卸载之前执行,它可以用来释放资源或取消定时器。

例如,假设我们有一个组件,它需要在每次重新渲染时设置一个定时器。我们可以使用 useEffect Hook 来实现这个功能,如下所示:

import { useEffect, useState } from "react";

const MyComponent = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <div>
      {count}
    </div>