设置状态导致REECT中的UI滞后

发布于 2025-02-04 14:07:45 字数 1299 浏览 3 评论 0原文

我有一个React应用程序,可以在容器小部件中列出卡片列表。容器小部件具有使用效应,我们可以在其中订阅可观察到的数组,然后更新该数组,然后将其用于渲染组件内的卡片。每当任何卡都更改时,可观察的发射新值会再次创建整个数组,因此所有卡都会重新渲染。但是,这种重新渲染会导致明显的UI滞后。

这是从容器组件中删除的代码版本。

const obsRef = useRef<Subscription>(null);
const [apiResArray, setApiResArray] = useState([]);

useEffect(() => {
    
    if(obsRef.current) obsRef.current.unsubscribe();

    const mySubscription = myObservable$(changingValue)
    .subscribe((val) => {
        setApiResArray(val.apiArray);
    });

    obsRef.current = mySubscription;

    return () => {
      obsRef.current && obsRef.current.unsubscribe();
    };

}, [changingValue])
return (
    <CardWrapper $showMenu={showMenu}>
        { apiResArray.map((res, resIndex) => {
            return (
                <Card
                    data={{
                        // a json object with props
                    }}
                    key={res?.hKey}
                />
            );
        })}
    </CardWrapper>
);

card组件此处只需根据传递给它的道具呈现内容即可。我知道,由于数据是一个对象,因此参考平等可能会失败,并且我尝试记忆组件,但即使这也无济于事。

这些组件还有很多,但是发布所有代码没有意义。我想了解可能导致列表重新渲染的繁重操作,以至于整个UI被卡住了一两秒钟。该数组仅包含大约100个对象左右。每当更改效果更改时,它就会发生。我可以根据需要共享更多信息。

高度赞赏有关提高性能的任何建议。

I have a react app that renders a list of cards in a container widget. The container widget has a useEffect where we subscribe to an observable and update the array that is then used to render the cards inside the component. Each time any of the cards change, the observable emits new values resulting in creating of the array all over again and thus all the cards are re-rendered. However this re-render causes a noticeable UI lag.

Here is the stripped down version of code from the container component.

const obsRef = useRef<Subscription>(null);
const [apiResArray, setApiResArray] = useState([]);

useEffect(() => {
    
    if(obsRef.current) obsRef.current.unsubscribe();

    const mySubscription = myObservable$(changingValue)
    .subscribe((val) => {
        setApiResArray(val.apiArray);
    });

    obsRef.current = mySubscription;

    return () => {
      obsRef.current && obsRef.current.unsubscribe();
    };

}, [changingValue])
return (
    <CardWrapper $showMenu={showMenu}>
        { apiResArray.map((res, resIndex) => {
            return (
                <Card
                    data={{
                        // a json object with props
                    }}
                    key={res?.hKey}
                />
            );
        })}
    </CardWrapper>
);

The Card component here simply renders the content based on props passed to it. I know that since data is an Object, referential equality may fail and I have tried memoizing the component but even that does not help.

There is a lot more to these components but posting all the code won't make sense. I wish to understand what possibly might be causing the list re-render to be such a heavy operation that the whole UI gets stuck for a second or two. The array contains around only 100 objects or so. It happens whenever changingValue changes. I can share more information as required.

Any suggestions on improving the performance are highly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城°AllureLove 2025-02-11 14:07:45

React将安装和卸载 dev 模式中的组件,以验证效果清洁剂和任何副作用。

我担心该订阅并取消订阅您的效果。

如果您想定义更改值,为什么不将其包装在if语句中?

if (changingValue) {
    const mySubscription = myObservable$(changingValue)
    .subscribe((val) => {
        setApiResArray(val.apiArray);
    });

    obsRef.current = mySubscription;
}

另一个观察结果是渲染

<Card
  data={
    {
      // a json object with props
    }
  }
  key={res?.hKey} // Why is this a falsy value ?
/>

虚假价值的项目可以使重新渲染组件的关键道具更改,一个具有内部钥匙值,另一个带有您的实现值

React will mount and unmount the component in DEV mode to validate effect cleaner and any side effect.

I'm concerned about that subscribe and unsubscribe in your effect.

If you want changingValue to be defined why not just wrap it inside an if statement ?

if (changingValue) {
    const mySubscription = myObservable$(changingValue)
    .subscribe((val) => {
        setApiResArray(val.apiArray);
    });

    obsRef.current = mySubscription;
}

Another observation is at render of items

<Card
  data={
    {
      // a json object with props
    }
  }
  key={res?.hKey} // Why is this a falsy value ?
/>

Falsy value can make key prop change those re-rendering the component, one with React internal key value and another with your implementation value

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文