Wrap components with a debounce
, throttle
, or any other delayed-rendering method, to stop them from re-rendering often when their props change.
React.memo
can be used to control whether a certain (wrapped) component should be rendered or not,
by providing it with custom method as the a second parameter, but memo
is unhelpful in some situations.
Sometimes it is wished to limit the number of times a component is rendered, for example, to a specific FPS or just to debounce it, so if it is called often, with different props, it will only actually re-render once those often calls are ceased (for enough time).
Sometimes components are very "expensive" to to re-render, in terms of performance (intense CPU usage), or they do async operations such as network requests.
Assuming the parent-component which is causing these re-renders (by updating props often) cannot be refactored, or the cause is a deep mystery (due to code complexity),
then wrapping those often-rendered components with bouncer
HOC should alleviate the symptoms.
Use from CDN / Download from this repo / NPM
npm i @yaireo/react-bouncer -S
import bouncer from '@yaireo/react-bouncer'
import throttle from 'lodash.throttle' // throttle example
// simplified example for a component which gets rendered often due to props change
const Foo = ({x,y}) => `${x} ${y}`
// uses 300ms `debounce` by default
const DebouncedFoo = bouncer(Foo)
DebouncedFoo.displayName = 'DebouncedFoo'
// use a `throttle` method instead of the default `debounce` (or use your own custom one)
const ThrottleddFoo = bouncer(Foo, 300, throttle)
ThrottleddFoo.displayName = 'ThrottleddFoo'
// use them in another component which might render them often with different props
const App = () => {
const [pos, setPos] = useState({x:0, y:0})
// re-render on mouse move
useEffect(() => {
const onMouseMove = e => setPos({x: e.pageX, y: e.pageY})
window.addEventListener('mousemove', onMouseMove)
return () => window.removeEventListener('mousemove', onMouseMove)
}, [])
return <>
<DebouncedFoo {...pos}/>
<ThrottleddFoo {...pos}/>
</>
}