面试题答案
一键面试思路
- 理解依赖数组作用:依赖数组是Hooks(如
useEffect
、useCallback
、useMemo
)用来决定何时重新执行副作用、重新生成回调函数或重新计算 memoized 值的依据。 - 确定真正依赖:对于复杂React应用,需要梳理状态和副作用之间的关系,明确哪些状态或变量的变化会影响副作用的执行逻辑。只将这些真正影响副作用逻辑的变量放入依赖数组。
- 避免过度依赖:如果依赖数组中包含不必要的变量,会导致副作用不必要的频繁执行,降低性能。例如,一个与副作用执行逻辑无关的组件内部状态变化,不应该触发该副作用。
- 处理相互关联状态:当状态相互关联时,要综合考虑这些状态对副作用的影响。可能需要将相关联的状态都放入依赖数组,或者通过一些方式将这些关联状态合并成一个值放入依赖数组。
代码示例
假设我们有一个复杂的用户管理应用,用户信息包括姓名、年龄,且有一个副作用用于根据用户信息更新本地存储,并在页面标题显示用户信息。
import React, { useState, useEffect } from'react';
const UserManagement = () => {
const [userName, setUserName] = useState('');
const [userAge, setUserAge] = useState(0);
// 合理设置依赖数组
useEffect(() => {
localStorage.setItem('userInfo', JSON.stringify({ name: userName, age: userAge }));
document.title = `User: ${userName}, Age: ${userAge}`;
}, [userName, userAge]);
return (
<div>
<input
type="text"
placeholder="Name"
value={userName}
onChange={(e) => setUserName(e.target.value)}
/>
<input
type="number"
placeholder="Age"
value={userAge}
onChange={(e) => setUserAge(parseInt(e.target.value, 10))}
/>
</div>
);
};
export default UserManagement;
不同设置对性能的影响
- 依赖数组缺失关键依赖:
- 例如,如果
useEffect
中遗漏了userAge
在依赖数组中,当userAge
变化时,本地存储和页面标题不会更新,导致数据不一致。 - 代码如下:
- 例如,如果
useEffect(() => {
localStorage.setItem('userInfo', JSON.stringify({ name: userName, age: userAge }));
document.title = `User: ${userName}, Age: ${userAge}`;
}, [userName]); // 遗漏 userAge
- 依赖数组包含不必要依赖:
- 假设组件中有一个与用户信息无关的加载状态
isLoading
,如果将其放入依赖数组:
- 假设组件中有一个与用户信息无关的加载状态
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
localStorage.setItem('userInfo', JSON.stringify({ name: userName, age: userAge }));
document.title = `User: ${userName}, Age: ${userAge}`;
}, [userName, userAge, isLoading]); // 包含不必要的 isLoading
- 每次`isLoading`变化时,即使`userName`和`userAge`没有改变,副作用也会重新执行,导致不必要的本地存储操作和页面标题更新,浪费性能。