【问题标题】:React performing slow on extreme socket updatesReact 在极端套接字更新上执行缓慢
【发布时间】:2020-12-03 03:45:57
【问题描述】:

我正在构建一个交易应用程序并在服务器端使用节点并在客户端做出反应。我目前面临的问题是关于非常频繁更新的反应性能。

我的过程描述如下。

我最常见的情况是两个表格显示期权数据看涨和看跌。每个表最少有两行,最多有 8 行,所以我们一次最多可以有 16 行。每行最多可以有 30 列。

为了更新,我使用的是套接字连接。每当在任何选项列中发生简单的更改时,会发生从套接字服务器发出的事件,我将在客户端侦听。

通过套接字在客户端获取数据后,我可以搜索更新数据的特定行和列,然后使用旧数据和新数据重新构建所有 16 行的全部数据,然后调度操作。 .. 这种更新非常频繁地发生,例如每毫秒 1000 次更新中的 100 次,因此整个表被重新渲染并导致我的应用程序变慢。

我正在使用 redux 来管理我的 react 应用程序中的状态

【问题讨论】:

  • 我的猜测是您没有使用纯组件(扩展 PureComponent 或使用 React.memo),并且可能会传递导致不必要的重新渲染的道具(从状态映射)。如果套接字消息不必要地更新了整个页面,您可能会看到一些性能问题。
  • 我错过了这个:100s of 1000s of updates per millisecond 但尚未发明出刷新率为 100 万的显示器,因此每秒更新超过 60 次是没有意义的。

标签: node.js reactjs performance socket.io react-redux


【解决方案1】:

这是一个纯组件的示例,每秒更新大约 100 次没有问题:

const { useState, memo, useEffect, useRef } = React;

const COLUMS = 31;
const ITEM_COUNT = COLUMS * COLUMS;
const TIMER = 10;
const COLORS = ['red', 'green', 'blue'];
const nextColor = ((current) => () =>
  COLORS[++current % COLORS.length])(0);
const next = ((num) => () => ++num % ITEM_COUNT)(-1);
const Item = memo(function Item({ color }) {
  return (
    <td
      style={{
        border: '1px solid black',
        minWidth: '20px',
        minHeight: '20px',
        backgroundColor: color,
        transitionDuration: '2s',
        transitionTimingFunction: 'ease-out',
        transitionProperty: 'color, background-color',
      }}
    >
      &nbsp;
    </td>
  );
});

const Row = memo(function Row({ items }) {
  return (
    <tr>
      {items.map((item) => (
        <Item key={item.id} color={item.color} />
      ))}
    </tr>
  );
});

const App = () => {
  const r = useRef(0);
  r.current++;
  const [data, setData] = useState(
    new Array(ITEM_COUNT)
      .fill('')
      .map((_, id) => ({ id, color: 'red' }))
      .reduce((result, item, index) => {
        if (index % COLUMS === 0) {
          result.push([]);
        }
        result[result.length - 1].push(item);
        return result;
      }, [])
  );
  useEffect(() => {
    const i = setInterval(
      () =>
        setData((data) => {
          const change = next(), //id to change
            color = nextColor(); //new value for color
          return data.map(
            (items) =>
              //do not update items if id is not in this row
              items.find(({ id }) => id === change)
                ? //update the one item that has id of change
                  items.map(
                    (item) =>
                      item.id === change
                        ? { ...item, color } //change the color
                        : item //return the item unchanged
                  )
                : items //id is not in this row return items unchanged
          );
        }),
      TIMER
    );
    return () => clearInterval(i);
  }, []);
  return (
    <div>
      <h1>rendered: {r.current}</h1>
      <table>
        <tbody>
          {data.map((items, index) => (
            <Row key={index} items={items} />
          ))}
        </tbody>
      </table>
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【讨论】:

    【解决方案2】:

    我不知道您为什么如此频繁地重新渲染组件,但您可以尝试限制对 redux 存储的更新。这样,您就可以向用户显示所有最新数据,而不会增加 CPU 的负担。

    您可以使用throttle-debounce 包来限制您的套接字回调。仅当自上次调用以来已超过给定时间间隔时,对受限制函数的后续调用才会成功。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 1970-01-01
      • 1970-01-01
      • 2013-11-06
      相关资源
      最近更新 更多