You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用useMemo()无法阻止React组件额外重渲染?

解决组件重复渲染问题的正确方法

首先要明确:useMemo 并不是用来阻止组件重渲染的工具——它的作用是缓存昂贵计算的结果,避免每次渲染都重复执行计算。组件依然会在依赖的状态或 props 变化时重新渲染,包括你通过 useAppSelector 获取的 Redux 状态变化时。

你看到 console.log 反复输出,大概率是以下几种原因:

  1. 组件初始渲染时,blogs 是初始状态(比如空数组);
  2. useEffect 触发异步请求后,Redux 状态更新(比如 loading 状态变化、数据加载完成),导致组件重新渲染;
  3. 可能存在不必要的状态更新,比如请求完成后重复设置相同的 results 数组,或者父组件触发了重渲染。

下面是针对性的解决方案:

1. 用 reselect 缓存选择器结果

如果你的选择器每次都返回新的数组引用(比如 Redux 切片中每次更新状态时都创建新的 results 数组),即使数据内容没变化,useAppSelector 也会因为引用不同触发重渲染。这时可以用 Redux Toolkit 内置的 createSelector 来创建缓存的选择器:

import { createSelector } from '@reduxjs/toolkit';

// 先定义基础选择器
const selectIntroBlogsData = (state: RootState) => state.introBlogsSlice.data;

// 创建缓存的选择器,只有当 data.results 实际变化时才返回新值
const selectBlogs = createSelector(
  [selectIntroBlogsData],
  (data) => data.results
);

// 在组件中使用
const blogs = useAppSelector(selectBlogs);

2. 用 React.memo 包裹组件

如果组件的重渲染是因为父组件重渲染导致的(而非自身依赖的状态变化),可以用 React.memo 包裹组件,它会浅比较组件的 props,只有当 props 变化时才触发重渲染:

const BlogsComponent = React.memo(() => {
  const blogs = useAppSelector(selectBlogs);
  const dispatch = useAppDispatch();

  useEffect(() => {
    dispatch(fetchSomeBlogs());
  }, []);

  console.log("blogs", blogs);

  return (
    // 组件内容
  );
});

3. 检查 Redux 切片中的不必要状态更新

确保你的 reducer 只在数据真正变化时才更新状态。比如在异步请求完成的 case 中,先判断新数据是否和当前状态一致,一致的话直接返回原状态:

import { isEqual } from 'lodash'; // 可以用 lodash 的深比较工具

case fetchSomeBlogs.fulfilled:
  // 对比新数据和当前数据,一致则不更新
  if (isEqual(state.data.results, action.payload.results)) {
    return state;
  }
  return {
    ...state,
    data: {
      ...state.data,
      results: action.payload.results,
      loading: false
    }
  };

4. 确认 useEffect 只执行一次

检查你的 useEffect 是否意外触发多次。可以在 useEffect 内加日志确认:

useEffect(() => {
  console.log("Dispatching fetchSomeBlogs");
  dispatch(fetchSomeBlogs());
}, []);

如果日志输出多次,说明组件可能被多次挂载/卸载,或者依赖数组有误(但你这里是空数组,应该只执行一次)。

内容的提问来源于stack exchange,提问作者Vilayat Safarov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:46:21