返回

React 18 源码深探:剖析 useMemo、useCallback 和 memo

前端

在 React 的浩瀚宇宙中,useMemo、useCallback 和 memo 这三位密友扮演着举足轻重的角色。它们携手合作,优化组件的性能,让 React 应用如丝般顺滑。为了更深入地了解它们的奥秘,我们不妨踏入 React 18 的源码,来一场说走就走的技术之旅!

序幕:初识 useMemo 和 useCallback

useMemo 和 useCallback 就像两个聪明的记忆大师,它们记住组件中的值和函数,在组件重新渲染时,只有当它们依赖项发生变化时,才重新计算。useMemo 用于存储值,而 useCallback 用于存储函数。这样一来,既避免了不必要的计算,又确保了组件状态的稳定性。

核心:源码剖析

useMemo 的源码中,我们发现了这样一行代码:

const prevState = ReactCurrentDispatcher.current.memoizedState;

它获取了组件当前的 memoizedState,如果它与新的 memoizedState 相同,则表明依赖项没有变化,useMemo 返回之前存储的值。否则,它会重新计算值并返回新的 memoizedState。

useCallback 的源码也类似:

const prevState = ReactCurrentDispatcher.current.memoizedState;
const prevCallback = prevState[0];

它获取了 useCallback 存储的先前回调函数。如果它与新的回调函数相同,则返回先前回调函数。否则,它会创建一个新的回调函数并返回。

第三位成员:memo

memo 是一个高阶组件,它将一个函数组件包装起来,并使用 useMemo 来记忆组件的 props。当 props 没有变化时,memo 阻止组件重新渲染。这对于优化渲染密集型组件非常有用。

实战:用例演示

让我们用一个实际例子来理解这些概念。假设我们有一个组件,它有一个值列表,并根据一个过滤器进行过滤。

function MyComponent() {
  const [filter, setFilter] = useState('');
  const filteredList = useMemo(() => filterList(list, filter), [filter]);
  return (
    <ul>
      {filteredList.map(item => <li key={item}>{item}</li>)}
    </ul>
  );
}

在这个例子中,useMemo 确保了当 filter 发生变化时,filteredList 才重新计算。如果 filter 没有变化,则返回之前的 filteredList。这避免了不必要的重新渲染,从而提高了组件的性能。

结语:化繁为简

useMemo、useCallback 和 memo 是 React 18 中强大的工具,它们通过记忆值和函数,优化了组件的性能。通过源码分析,我们揭示了它们的内部机制,加深了对它们工作原理的理解。掌握这些概念,你将成为 React 开发中的性能大师,让你的应用飞驰如电!