useFocusEffect
useFocusEffect
是 React Navigation 提供的一个 Hook,专门用于处理页面获得焦点时的副作用。
基本用法:
import { useFocusEffect } from '@react-navigation/native';
import { useCallback } from 'react';
function MyScreen() {
useFocusEffect(
useCallback(() => {
// 页面获得焦点时执行的代码
console.log('页面获得焦点');
// 返回清理函数(可选)
return () => {
console.log('页面失去焦点');
};
}, [])
);
}
特点:
- 每次页面获得焦点时都会执行
- 支持清理函数,页面失去焦点时执行
- 常用于数据刷新、订阅管理等场景
useCallback
useCallback
是 React 提供的性能优化 Hook,用于缓存函数引用。
基本语法:
const memoizedCallback = useCallback(
() => {
// 函数逻辑
},
[dependency1, dependency2] // 依赖数组
);
工作原理:
- 只有当依赖数组中的值发生变化时,才会重新创建函数
- 如果依赖数组为空
[]
,函数只会创建一次 - 返回的是函数的缓存版本
使用场景:
防止子组件不必要的重渲染:
function Parent() { const [count, setCount] = useState(0); // 没有 useCallback - 每次渲染都创建新函数 const handleClick = () => { console.log('clicked'); }; // 使用 useCallback - 函数引用保持不变 const memoizedHandleClick = useCallback(() => { console.log('clicked'); }, []); return <Child onClick={memoizedHandleClick} />; }
与其他 Hook 配合使用:
function MyComponent() { const [data, setData] = useState(null); const fetchData = useCallback(async () => { const result = await api.getData(); setData(result); }, []); // 空依赖数组,函数只创建一次 useEffect(() => { fetchData(); }, [fetchData]); // fetchData 不会导致无限循环 }
性能考虑
useCallback 的使用原则:
考虑使用:
- 传递给子组件的函数
- 作为其他 Hook 的依赖
- 计算成本较高的函数
不考虑使用:
- 简单的事件处理函数(如果没有传递给子组件)
- 过度使用(useCallback 本身也有开销)
示例对比:
// 不需要 useCallback
function SimpleComponent() {
const handleClick = () => {
console.log('simple click');
};
return <button onClick={handleClick}>Click</button>;
}
// 需要 useCallback
function ComplexComponent({ children }) {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
// 复杂逻辑或传递给子组件
setCount(prev => prev + 1);
}, []);
return (
<div>
{React.Children.map(children, child =>
React.cloneElement(child, { onClick: handleClick })
)}
</div>
);
}
总结
- useFocusEffect:处理页面焦点变化的副作用,常用于数据刷新
- useCallback:缓存函数引用,优化性能,防止不必要的重渲染
- 结合使用:在导航场景中实现高效的数据刷新机制
这两个 Hook 在 React Native 应用中非常实用,特别是在处理页面导航和性能优化方面。