【问题标题】:How to reduce the number of times useEffect is called?如何减少调用useEffect的次数?
【发布时间】:2020-09-07 17:38:24
【问题描述】:

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,
})

然后我的组件被连接了,所以我在这里传递它

【问题讨论】:

  • 如何更新你的 user.data 字段
  • 触发一个发出请求的 redux 操作 > api gateway > lambda > firebase 来检索它们,然后将它们加载到我的 redux 存储中
  • user.data 是一个数组,Array 是一个引用类型。因此,如果您销毁旧数组并创建一个新数组,react 会将其检测为更改。
  • 那么user.data来自redux store?你怎么把它从商店里拿出来,你能给我们看看选择器吗?
  • @HMR yes 现在将添加代码

标签: javascript reactjs performance use-effect


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这不是一个答案,但有太多代码无法放入评论中。首先,您可以通过临时替换原始根减速器来记录更改 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 不断变化的另一件事是当您在 reducer 中执行类似操作时:

    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 也会以错误的方式显示差异,如果你在 state 中改变某些东西,devtools 会将它们显示为更改,但 React 不会将它们视为更改。当您将新对象分配给 data:[] 时,redux 不会将它们显示为更改,但 React 会将其视为更改。

    【讨论】:

    • 接受另一个答案,因为它给了我我需要的东西,但会赞成这个,因为它鼓励我去别处寻找!随时为 Q 投票,让我通过 1000 分:D
    • @RedBaron +1,恭喜超过 1000。效果一直被调用仍然没有意义。无论父级渲染子级多少次,效果仅在 state.user.data 更改时运行。
    • 是的,这是需要继续调查的事情,但重新渲染的数量至少有所下降,主要问题是我的动画在重新渲染时出现闪烁,但这已经解决了.所以短期我很高兴,长期我应该解决它。感谢您的帮助,很快就会在这个平台上再次见到你:D
    猜你喜欢
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    相关资源
    最近更新 更多