文章目录
一、useEffect 概念二、useEffect 的基本用法1. 无依赖项2. 空依赖项数组3. 带依赖项的 useEffect 三、useEffect 的常见应用场景1. 数据获取2. 订阅与清除3. 动画与定时器 四、useEffect 的进阶用法1. 多个 useEffect2. 条件执行副作用 五、注意事项
useEffect
是 React 钩子函数之一,它使函数组件能够执行副作用操作。常见的副作用包括数据获取、订阅、手动更改 React 组件中的 DOM 以及定时器等。在类组件中,我们通常在生命周期方法中执行这些操作,而在函数组件中,我们使用 useEffect
来完成这些任务。本文将详细介绍 useEffect
的概念、用法及其在实际开发中的应用,旨在帮助开发者全面掌握这一重要特性。
一、useEffect 概念
useEffect
钩子是 React 16.8 版本引入的,它允许我们在函数组件中执行副作用操作。useEffect
函数接收两个参数:
基本语法如下:
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> );}
五、注意事项
避免不必要的副作用:确保副作用函数只在需要时执行。使用依赖项数组来控制副作用的执行时机,避免不必要的重复执行。清除副作用:副作用函数返回的清除函数用于清理不再需要的副作用。例如,清除事件监听器、取消订阅或清除定时器等。依赖项数组:准确指定依赖项数组中的变量,确保副作用函数在依赖项发生变化时正确执行。遗漏或误包含依赖项可能导致副作用执行不符合预期。处理异步操作:在处理异步操作时,注意在组件卸载时取消未完成的请求,避免内存泄漏。性能优化:对于性能敏感的操作,确保合理使用useEffect
,避免过度渲染和不必要的副作用执行。 推荐:JavaScript