【React】useEffect 钩子详解

useEffect 是 React 钩子函数之一,它使函数组件能够执行副作用操作。常见的副作用包括数据获取、订阅、手动更改 React 组件中的 DOM 以及定时器等。在类组件中,我们通常在生命周期方法中执行这些操作,而在函数组件中,我们使用 useEffect 来完成这些任务。本文将详细介绍 useEffect 的概念、用法及其在实际开发中的应用,旨在帮助开发者全面掌握这一重要特性。

一、useEffect 概念

useEffect 钩子是 React 16.8 版本引入的,它允许我们在函数组件中执行副作用操作。useEffect 函数接收两个参数:

  1. 一个副作用函数。
  2. 一个依赖项数组(可选)。

基本语法如下:

useEffect(() => {
  // 副作用逻辑
  return () => {
    // 清除逻辑(可选)
  };
}, [依赖项]);

二、useEffect 的基本用法

1. 无依赖项

如果不传递依赖项数组,副作用函数会在每次渲染后执行。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('组件渲染或更新了');

    return () => {
      console.log('组件卸载了');
    };
  });

  return <div>Hello, useEffect!</div>;
}

上述代码中,console.log 会在每次组件渲染或更新时执行,而返回的清除函数会在组件卸载时执行。

2. 空依赖项数组

如果传递一个空数组作为依赖项,副作用函数只会在组件首次渲染时执行一次。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('组件首次渲染');

    return () => {
      console.log('组件卸载');
    };
  }, []);

  return <div>Hello, useEffect!</div>;
}

3. 带依赖项的 useEffect

如果传递一个依赖项数组,副作用函数会在依赖项发生变化时执行。

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    console.log(`Count 发生变化: ${count}`);

    return () => {
      console.log(`清除副作用: ${count}`);
    };
  }, [count]);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
    </div>
  );
}

上述代码中,当 count 发生变化时,副作用函数会执行,同时会先执行上一次渲染中的清除函数。

三、useEffect 的常见应用场景

1. 数据获取

在函数组件中使用 useEffect 可以方便地进行数据获取。

import React, { useState, useEffect } from 'react';

function DataFetchingComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));

    // 清除逻辑
    return () => {
      // 取消请求或其他清除操作
    };
  }, []); // 空依赖数组表示只在组件挂载和卸载时执行

  if (!data) {
    return <div>Loading...</div>;
  }

  return <div>{JSON.stringify(data)}</div>;
}

2. 订阅与清除

useEffect 也可以用于设置和清除订阅,例如事件监听器或 WebSocket 连接。

import React, { useEffect } from 'react';

function EventListenerComponent() {
  useEffect(() => {
    const handleResize = () => {
      console.log('窗口大小改变');
    };

    window.addEventListener('resize', handleResize);

    // 清除逻辑
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组表示只在组件挂载和卸载时执行

  return <div>请调整窗口大小查看效果</div>;
}

3. 动画与定时器

我们可以使用 useEffect 来设置和清除定时器或启动动画。

import React, { useState, useEffect } from 'react';

function TimerComponent() {
  const [count, setCount] = useState(0);

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

    // 清除逻辑
    return () => {
      clearInterval(intervalId);
    };
  }, []); // 空依赖数组表示只在组件挂载和卸载时执行

  return <div>计数: {count}</div>;
}

四、useEffect 的进阶用法

1. 多个 useEffect

在一个组件中可以使用多个 useEffect,每个 useEffect 可以负责不同的副作用操作。

import React, { useState, useEffect } from 'react';

function MultiEffectComponent() {
  const [count, setCount] = useState(0);
  const [data, setData] = useState(null);

  useEffect(() => {
    document.title = `计数: ${count}`;
  }, [count]);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <div>数据: {JSON.stringify(data)}</div>
    </div>
  );
}

2. 条件执行副作用

通过条件判断,可以有选择地执行副作用逻辑。

import React, { useState, useEffect } from 'react';

function ConditionalEffectComponent() {
  const [count, setCount] = useState(0);
  const [fetchData, setFetchData] = useState(false);
  const [data, setData] = useState(null);

  useEffect(() => {
    if (fetchData) {
      fetch('https://api.example.com/data')
        .then(response => response.json())
        .then(data => setData(data));
    }
  }, [fetchData]);

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <button onClick={() => setFetchData(true)}>获取数据</button>
      <div>数据: {JSON.stringify(data)}</div>
    </div>
  );
}

五、注意事项

  1. 避免不必要的副作用:确保副作用函数只在需要时执行。使用依赖项数组来控制副作用的执行时机,避免不必要的重复执行。
  2. 清除副作用:副作用函数返回的清除函数用于清理不再需要的副作用。例如,清除事件监听器、取消订阅或清除定时器等。
  3. 依赖项数组:准确指定依赖项数组中的变量,确保副作用函数在依赖项发生变化时正确执行。遗漏或误包含依赖项可能导致副作用执行不符合预期。
  4. 处理异步操作:在处理异步操作时,注意在组件卸载时取消未完成的请求,避免内存泄漏。
  5. 性能优化:对于性能敏感的操作,确保合理使用 useEffect,避免过度渲染和不必要的副作用执行。

推荐:JavaScript


在这里插入图片描述

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter-Lu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值