Prevent rerender using React hooks and onScroll or onWheel

Viewed 675

I have a component where I use the onWheel event to detect scrolling in all directions (this works). My problem is preventing this component to rerender so I can utilize throttle from underscore.js:

Example

import React, {useState} from 'react';
import { throttle } from 'underscore';

const App = () => {
  const [position, setPosition] = useState({x: 0, y: 0});
  const updatePosition = throttle((e) => {
    e.preventDefault(); // Required for left/right swiping.

    setPosition({
      x: position.x + e.deltaX,
      y: position.y + e.deltaY,
    });
  }, 1000);

  return (
    <div className="viewport" onWheel={updatePosition}>
      <Box x={position.x} y={position.y} />
    </div>
  );
};

export default App;

The throttle function does not work here, since every time the state updates the component rerenderes.

2 Answers

Can you please try the below one. I just wrapped the throttle with the new function.

import { throttle } from "underscore";

import Box from "./Box";

const App = () => {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  function updatePosition(e) {
    e.preventDefault(); // Required for left/right swiping.

    throttle(e => {
      setPosition({
        x: position.x + e.deltaX,
        y: position.y + e.deltaY
      });
    }, 1000)(e);
  }

  return (
    <div className="viewport" onWheel={updatePosition}>
      <Box posX={position.x} posY={position.y} />
    </div>
  );
};

export default App;

Edit gifted-sun-i9ism

You can throttle rendering of a component using the throttle function from underscore by creating a new component called ThrottledBox.

export default function App() {
  const [position, setPosition] = React.useState({ x: 0, y: 0 });

  function handleOnWheen(e) {
    e.preventDefault(); // Required for left/right swiping.
    setPosition({
      x: position.x + e.deltaX,
      y: position.y + e.deltaY
    });
  }

  return (
    <div className="viewport" onWheel={handleOnWheen}>
      <ThrottledBox x={position.x} y={position.y} />
    </div>
  );
}

const ThrottledBox = throttle((props) => <Box {...props}/>, 1000);

https://codesandbox.io/s/zealous-booth-x8lfd

Related