如何减少调用 useEffect 的次数?

How to reduce the number of times useEffect is called?

Google 的灯塔工具给我的应用程序带来了令人震惊的性能得分,因此我一直在进行一些调查。我有一个名为 Home

的组件

里面 Home 我有 useEffect(只有一个)看起来像这样

useEffect(() => {
    console.log('rendering in here?') // called 14 times...what?!
    console.log(user.data, 'uvv') // called 13 times...again, What the heck?
}, [user.data])

我知道您放置了 [] 的第二个参数,以确保 useEffect 仅在数据更改后才被调用,但这是我不明白的主要部分。当我控制台日志 user.data 时,前 4 个控制台日志是空数组。接下来的 9 个是长度为 9 的数组。所以在我看来,它应该只调用了两次?一次用于 [] 一次用于 [].length(9) 那么到底发生了什么?

我真的需要减少它,因为它一定会影响我的表现。如果我还能做些什么来显着减少这些电话,请告诉我

我就是这样得到的user.data

const Home = ({ ui, user }) => { // 我把它作为道具传入这里

const mapState = ({ user }) => ({
    user,
})

然后我的组件已连接,所以我将其传递到这里

为了克服这种情况,React Hooks 还提供了称为 useMemo 的功能。 您可以使用 useMemo 而不是 useEffect,因为 useMemo 缓存它渲染的实例,并且每当它命中渲染时,它首先检查缓存以查看是否有任何相关实例可用于给定的 deps。如果是这样,那么而不是 运行 整个函数它将简单地return它从缓存中。

这不是答案,但代码太多,无法放入评论中。首先,您可以通过临时替换原始根减速器来记录所有更改 user.data 的操作:

let lastData = {};
const logRootReducer = (state, action) => {
  const newState = rootReducer(state, action);
  if (newState.user.data !== lastData) {
    console.log(
      'action changed data:',
      action,
      newState.user.data,
      lastData
    );
    lastData = newState.user.data;
  }
  return newState;
};

导致 user.data 不断变化的另一件事是当你在减速器中做这样的事情时:

if (action.type === SOME_TYPE) {
  return {
    ...state,
    user: {
      ...state.user,
      //here data is set to a new array every time
      data: [],
    },
  };
}

相反,您可以这样做:

const EMPTY_DATA = [];
//... other code
data: EMPTY_DATA,

您的选择器正在 user 脱离状态并创建一个会导致组件重新渲染的新对象,但效果的依赖性是 user.data 因此效果只会 运行 如果数据实际改变了。

Redux devtools 也以错误的方式显示差异,如果你改变状态中的某些东西,devtools 会将它们显示为更改,但 React 不会将它们视为更改。当您将新对象分配给某物时 data:[] 然后 redux 不会将它们显示为更改但 React 会将其视为更改。