如何解决上下文中重新渲染过多的问题?

IT技术 javascript reactjs
2021-04-15 07:15:51

每当我更新user对象中)users阵列在上下文中) -它使用的所有组件users重新呈现。


我试过的

我有一个使用上下文中的值的组件:

const DashboardCardList=()=> {
    const context = useContext(StaticsContext);
    const users = context.users.filter(user=>user.visible);

    return !users
        ? <Loading/>
        : (
            <Container>
                {users.map(user=>
                    <DashboardCard key={user._id} user={user}/>
                )}
            </Container>
        );
};

我的更新功能(更新上下文状态):

const onUserUpdate=(user)=>{
   const index = this.state.users.findIndex(item => item._id === user._id);
   const users = [...this.state.users]
   users[index] = user;
   this.setState({users:users});
}

最终组件:

const DashboardCard=({user})=> {
    console.log("I'm here!", user);
    return ...;
}

问题

为什么它不断重新渲染是因为上下文吗?
如何正确地写这个?

1个回答

上下文消费者 ( v17)没有渲染救助

这是一个演示,Consumer即使他不消费任何东西,也会因为他是上下文消费者而总是重新渲染。

import React, { useState, useContext, useMemo } from "react";
import ReactDOM from "react-dom";

// People wonder why the component gets render although the used value didn't change
const Context = React.createContext();

const Provider = ({ children }) => {
  const [counter, setCounter] = useState(0);
  const value = useMemo(() => {
    const count = () => setCounter(p => p + 1);
    return [counter, count];
  }, [counter]);
  return <Context.Provider value={value}>{children}</Context.Provider>;
};

const Consumer = React.memo(() => {
  useContext(Context);
  console.log("rendered");
  return <>Consumer</>;
});

const ContextChanger = () => {
  const [, count] = useContext(Context);
  return <button onClick={count}>Count</button>;
};

const App = () => {
  return (
    <Provider>
      <Consumer />
      <ContextChanger />
    </Provider>
  );
};

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

编辑上下文 API 问题

要解决这个问题:

  • 为每个消耗的值使用单个上下文。这意味着上下文包含单个值,(不,应用程序中的多个上下文没有问题)。
  • 使用状态管理解决方案,如 Recoil.js、Redux、MobX 等(虽然这可能有点矫枉过正,但请事先考虑好应用程序设计)。
  • 可以通过使用.memoizing Provider 的值useMemo来实现较小的优化
谢谢你的提示。是的,Redux 似乎对这个有点矫枉过正。据我了解您的第一点,我可以为每个用户或createStore()为每个用户提供一个单一的上下文,使用可重用的库 - 对吗?问题是上下文不仅仅存储用户。它还存储另一个实体(项目、客户)。它可能会有点过度上下文,不是吗?
2021-05-24 07:15:51
不知道“窃取另一个用户的焦点”是什么意思,但如果您记住愚蠢的组件(不使用上下文的组件),UI 将不会重新呈现,因此用户不应注意到屏幕上的任何变化。
2021-05-29 07:15:51
嗯,但我同时使用所有这些值 - 一直。这就是为什么它们处于相同的上下文中。那么这是否意味着如果我有 40 个用户 - 我有 40 个上下文?性能在这里不是问题。它是 websocket 应用程序,每次重新渲染都在窃取其他用户的注意力等。
2021-06-03 07:15:51
问题是开发人员将所有内容都放在一个上下文中,只需根据您的需要拆分它。不用担心重新渲染而没有真正的性能问题,典型的应用程序并没有 - 大 - 使用 - 足以考虑考虑性能
2021-06-12 07:15:51
不,您描述的问题是您有侦听数据和渲染 UI 的组件,它应该分开,获取数据的组件和仅用于查看的组件,这样 UI 在不需要时就不会闪烁。
2021-06-17 07:15:51