React father::
effect
梗概
- 在React中,effect是一个重要的概念,用于处理组件的副作用操作。副作用操作指的是对外部资源的访问,比如数据获取、订阅事件、手动修改DOM等。
- 只能监听state
- 因次想要触发effect, 就一定会导致组件重新渲染
实际应用
指向原始笔记的链接
- child::
避免不必要的effect
示例
For example, you don’t need an Effect to adjust some state based on other state:
function Form() { const [firstName, setFirstName] = useState('Taylor'); const [lastName, setLastName] = useState('Swift'); // 🔴 Avoid: redundant state and unnecessary Effect const [fullName, setFullName] = useState(''); useEffect(() => { setFullName(firstName + ' ' + lastName); }, [firstName, lastName]); // ... }上面的写法是多余的,和下面代码的作用完全一致:
function Form() { const [firstName, setFirstName] = useState('Taylor'); const [lastName, setLastName] = useState('Swift'); // ✅ Good: calculated during rendering const fullName = firstName + ' ' + lastName; // ... }指向原始笔记的链接
- base::函数组件的生命周期钩子
使用effect
在函数式组件中使用effect时,可以通过useEffect来定义effect函数。该函数会在组件渲染完成后执行,并且可以返回一个清除函数用于清理effect。
useEffect(() => {
// effect逻辑
return () => {
// 清理逻辑
};
}, [dependencies]);- 怎么获取更新前的值: [child::实现获取state前一个值]
- 对比: useEffect与useLayoutEffect的对比
控制effect执行时机
- base::effect执行时机
- 可以通过第二个参数传入一个数组。effect会监听数组元素的变化
- 在目标变化后调用回调函数(其实还要先调用清理函数)
- 所以直接访问state就是更新后的值
- 在目标变化后调用回调函数(其实还要先调用清理函数)
- 如果不传入依赖项数组,它只会在组件挂载时运行一次(类似于
componentDidMount)。
监听props变化
- 虽然props是常量,但useEffect可以监听props的变化
- 每当父组件传入新的props值时,子组件会重新渲染
- useEffect可以通过依赖数组监听到props的变化
- 这对于需要响应props变化执行副作用操作很有用
- 例如:基于props变化更新组件内部状态、触发API调用等
function ProfilePage({ userId }) {
const [userData, setUserData] = useState(null);
// 当userId props变化时,重新获取用户数据
useEffect(() => {
async function fetchUserData() {
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUserData(data);
}
fetchUserData();
}, [userId]); // 监听userId props变化
if (!userData) return <div>Loading...</div>;
return <div>{userData.name}'s Profile</div>;
}代码示例
import React, { useEffect, useState } from 'react';
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
return () => {
document.title = 'React App';
};
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
};
export default MyComponent;这个例子中,我们使用useEffect来监听count的变化。每次点击按钮增加计数时,页面的标题也会随之改变。同时,我们在返回的清理函数中将标题还原为默认值。
异步与清理
- effect 的回调不应标记为
async,否则无法返回清理函数。应在回调内部启动异步任务,并在清理函数中取消未完成任务,避免内存泄漏。 - 参见:useEffect异步与清理、useEffect清理函数执行时机、避免不必要的effect