useEffect
是 React 中用于处理副作用操作的 Hook。副作用包括数据获取、订阅操作、手动修改 DOM 等。以下是一些 useEffect
的示例以及需要注意的知识:
1. 数据获取
import React, { useState, useEffect } from 'react';
function DataFetching() {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
};
fetchData();
}, []); // 空数组作为依赖表示只在组件挂载时执行一次
return (
<div>
{data && <p>Data: {data}</p>}
</div>
);
}
- 需要注意的知识:
- 异步操作应当在
useEffect
内部进行,以确保在组件渲染完成后执行。 - 使用空依赖数组
[]
可以确保useEffect
仅在组件挂载时执行一次。
- 异步操作应当在
2. 订阅操作
import React, { useState, useEffect } from 'react';
function Subscription() {
const [count, setCount] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setCount(prevCount => prevCount + 1);
}, 1000);
return () => {
clearInterval(intervalId);
};
}, []); // 空数组作为依赖表示只在组件挂载时执行一次
return (
<div>
<p>Count: {count}</p>
</div>
);
}
- 需要注意的知识:
useEffect
可以返回一个清理函数,在组件销毁时执行,用于清除副作用,比如取消订阅、清除定时器等。
3. 监听属性变化
import React, { useState, useEffect } from 'react';
function PropChanges({ prop }) {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1);
}, [prop]); // 当 prop 变化时触发 useEffect
return (
<div>
<p>Count: {count}</p>
</div>
);
}
- 需要注意的知识:
- 通过传递一个包含变量的数组作为
useEffect
的依赖,可以监听该变量的变化并执行相应的副作用操作。
- 通过传递一个包含变量的数组作为
4. 手动修改 DOM
import React, { useEffect } from 'react';
function DOMManipulation() {
useEffect(() => {
document.title = 'New Title';
return () => {
document.title = 'Original Title';
};
}, []); // 空数组作为依赖表示只在组件挂载时执行一次
return (
<div>
<p>DOM Manipulation Example</p>
</div>
);
}
- 需要注意的知识:
- 在
useEffect
内部可以进行一些 DOM 操作,但是需要确保操作不会导致 React 和 DOM 同步问题。 - 返回的清理函数可以用来恢复原始状态,以避免内存泄漏或者其他副作用。
- 在
5. 使用多个 useEffect
import React, { useState, useEffect } from 'react';
function MultipleEffects() {
const [count, setCount] = useState(0);
const [data, setData] = useState(null);
useEffect(() => {
// effect for count
document.title = `Count: ${count}`;
return () => {
document.title = 'Original Title';
};
}, [count]); // 当 count 变化时触发 useEffect
useEffect(() => {
// effect for data
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
};
fetchData();
return () => {
// cleanup for data
};
}, []); // 空数组作为依赖表示只在组件挂载时执行一次
return (
<div>
<p>Count: {count}</p>
{data && <p>Data: {data}</p>}
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
- 需要注意的知识:
- 可以在同一个组件中使用多个
useEffect
,每个useEffect
之间相互独立。 - 每个
useEffect
可以有自己的清理函数。
- 可以在同一个组件中使用多个
useEffect
的依赖可以分为三种情况:
- 空依赖数组:表示
useEffect
仅在组件挂载时执行一次。 - 包含具体依赖的数组:表示
useEffect
会在指定依赖发生变化时执行。 - 没有依赖数组:表示
useEffect
在每次组件渲染时都会执行。
下面是针对每种情况的详细示例以及注意知识:
1. 空依赖数组
import React, { useState, useEffect } from 'react';
function EmptyDependencyExample() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Component mounted");
return () => {
console.log("Component unmounted");
};
}, []); // 空依赖数组表示仅在组件挂载和卸载时执行
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default EmptyDependencyExample;
- 注意知识:
- 使用空依赖数组
[]
可以确保useEffect
仅在组件挂载时执行一次。 - 清理函数用于执行清理工作,比如取消订阅、清除定时器等。
- 使用空依赖数组
2. 具体依赖的数组
import React, { useState, useEffect } from 'react';
function DependencyArrayExample({ prop }) {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Component mounted or prop changed");
// 每次 prop 或 count 变化时都会触发 useEffect
return () => {
console.log("Component unmounted or prop changed");
};
}, [prop, count]); // 传入依赖数组表示当其中任一依赖变化时执行
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default DependencyArrayExample;
- 注意知识:
- 通过传递一个包含变量的数组作为
useEffect
的依赖,可以监听该变量的变化并执行相应的副作用操作。 - 当数组中的任一依赖变化时,
useEffect
将会重新执行。
- 通过传递一个包含变量的数组作为
3. 没有依赖数组
import React, { useState, useEffect } from 'react';
function NoDependencyExample() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Component rendered");
return () => {
console.log("Component re-rendered");
};
}); // 没有依赖数组表示在每次组件渲染时执行
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default NoDependencyExample;
- 注意知识:
- 没有传递依赖数组时,
useEffect
在每次组件渲染时都会执行。 - 当需要在组件渲染时执行某些操作,而不是依赖于特定的变量时,可以使用没有依赖数组的
useEffect
。
- 没有传递依赖数组时,
一个函数组件中可以包含多个 useEffect
。每个 useEffect
都可以处理不同的副作用,使代码更模块化和可维护。下面是一个示例:
import React, { useState, useEffect } from 'react';
function MultipleEffectsExample() {
const [count, setCount] = useState(0);
const [data, setData] = useState(null);
// 第一个 useEffect 处理 count 的副作用
useEffect(() => {
document.title = `Count: ${count}`;
return () => {
document.title = 'Original Title';
};
}, [count]); // 依赖于 count 的变化
// 第二个 useEffect 处理 data 的副作用
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
};
fetchData();
return () => {
// 在组件卸载或者 data 更新时执行清理操作
// 比如取消请求等
};
}, [data]); // 依赖于 data 的变化
return (
<div>
<p>Count: {count}</p>
<p>Data: {data}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default MultipleEffectsExample;