react 中 useEffect Hook 作用
`useEffect`是一个用于处理副作用(Side Effects)的 Hook
一、处理副作用
1. 副作用的概念
副作用是指在组件渲染过程中执行的、会影响组件外部环境或具有外部可见影响的操作。
常见的副作用包括数据获取(如从服务器获取数据)、订阅外部数据源(如消息队列、事件总线)、手动操作 DOM(如修改页面标题、滚动位置)以及设置定时器等。
2. useEffect 基本用法
2.1 语法结构
`useEffect`接受两个参数,第一个参数是一个函数,称为副作用函数(Effect Function),在这个函数内部执行实际的副作用操作。第二个参数是一个可选的依赖项数组(Dependency Array)。
import React, { useEffect, useState } from "react";
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// 这是一个副作用函数,这里模拟从服务器获取数据
console.log("Fetching data...");
return () => {
// 可选的清理函数,用于在组件卸载或依赖项变化时清理副作用
console.log("Cleaning up...");
};
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default MyComponent;
在这个例子中,副作用函数在组件挂载时执行,因为依赖项数组为空(`[]`),表示这个副作用只在组件初始化时触发一次。副作用函数还返回了一个清理函数,用于在组件卸载或依赖项变化时执行清理操作。
二、模拟生命周期方法
1. 替代 componentDidMount
在类组件中,`componentDidMount`方法在组件挂载到 DOM 后立即执行。在函数组件中,可以使用`useEffect`来实现类似的功能。当`useEffect`的依赖项数组为空时,副作用函数在组件第一次渲染(挂载)后执行,相当于`componentDidMount`。
import React, { useEffect, useState } from "react";
const MyComponent = () => {
const [data, setData] = useState(null);
useEffect(() => {
// 模拟在组件挂载后获取数据,相当于componentDidMount
fetch("https://example.com/api/data")
.then((response) => response.json())
.then((jsonData) => setData(jsonData));
}, []);
return <div>{data ? <p>{data}</p> : <p>Loading...</p>}</div>;
};
export default MyComponent;
2. 替代 componentDidUpdate
在类组件中,`componentDidUpdate`方法在组件每次更新(`state`或`props`变化)后执行。在函数组件中,可以通过在`useEffect`的依赖项数组中指定依赖项来模拟`componentDidUpdate`。当依赖项发生变化时,副作用函数会重新执行,类似于`componentDidUpdate`。
import React, { useEffect, useState } from "react";
const MyComponent = () => {
const [count, setCount] = useState(0);
const [data, setData] = useState(null);
useEffect(() => {
// 当count变化时,重新获取数据,类似于componentDidUpdate
if (count > 0) {
fetch("https://example.com/api/data")
.then((response) => response.json())
.then((jsonData) => setData(jsonData));
}
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
{data ? <p>{data}</p> : <p>Loading...</p>}
</div>
);
};
export default MyComponent;
3. 替代 componentWillUnmount
在类组件中,`componentWillUnmount`方法在组件卸载前执行,用于清理资源。在函数组件中,`useEffect`的副作用函数返回的清理函数在组件卸载或依赖项变化时执行,从而替代了`componentWillUnmount`的功能。
import React, { useEffect, useState } from "react";
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => {
// 组件卸载或依赖项变化时清除定时器,相当于componentWillUnmount
clearInterval(timer);
};
}, []);
return (
<div>
<p>Count: {count}</p>
</div>
);
};
export default MyComponent;
三、依赖项管理和优化
1. 依赖项的作用
1.1 决定副作用执行时机
例如:如果一个副作用函数依赖于组件的某个状态值,将这个状态值放入依赖项数组中,那么当这个状态值改变时,副作用函数就会重新运行。这样可以确保副作用与组件的状态和属性保持同步。
2. 优化性能
例如:在不必要的时候重复获取数据或重新订阅事件,浪费资源并可能导致应用程序性能下降。
3. 优化策略和常见错误
3.1 空依赖项数组的优化与风险
例如:初始化数据获取或设置全局事件监听器。但如果在副作用函数中使用了组件的状态或属性,并且没有将它们包含在依赖项数组中,就会导致闭包问题。
import React, { useEffect, useState } from "react";
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// 错误:没有将count包含在依赖项数组中,导致闭包问题
console.log("Count:", count);
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default MyComponent;
3.2 正确指定依赖项
为了避免上述问题,需要将副作用函数中使用的所有组件的状态、属性以及其他外部函数(如果在副作用函数内部调用)都包含在依赖项数组中。
import React, { useEffect, useState } from "react";
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Count:", count);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default MyComponent;
原文地址:https://blog.csdn.net/weixin_64684095/article/details/143783697
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!