Sheikh Hammad
Sheikh Hammad

Reputation: 1

React performing slow on extreme socket updates

I'm building a trading application and using node on the server side and react on client side.The current issue which I'm facing is regarding react performance on very frequents updates.

My process is describe as below.

The most common case I have is two tables displaying option data call and put. Each table have min of two rows and max of 8, so in total we'll have max 16 rows at single time. Each row can have up to 30 columns.

For updating I'm using a socket connection. Whenever a simple change occur in any of option column occurs an event emits from socket server which I'll be listening on client side.

After getting the data on client side via socket I can search for the specific row and column that where to update the data then re build the whole data of all 16 rows using the old data and new data and then dispatch the action... this updates occurs very frequently like 100s of 1000s of updates per millisecond and because of which whole table got re rendered and causing my app slow down.

I'm using redux to manage state in my react application

Upvotes: 0

Views: 1718

Answers (2)

hackhan
hackhan

Reputation: 522

I don't know why you're rerendering your components so frequently, but you can try throttling the updates to your redux store. This way you'll show all the latest data to your user without overburdening the CPU.

You can use throttle-debounce package to throttle your socket callback. Subsequent calls to the throttled function will only succeed if a given interval has been passed since the last call.

Upvotes: 1

HMR
HMR

Reputation: 39250

Here is an example with pure components no problem updating about 100 times a second:

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>

Upvotes: 1

Related Questions