window-size icon indicating copy to clipboard operation
window-size copied to clipboard

Add ability to debounce window resize updates

Open camflan opened this issue 5 years ago • 10 comments

This allows a user to pass a debounceMs when calling useWindowSize in order to debounce the window resize events

camflan avatar Oct 26 '18 04:10 camflan

please don't include formatting changes with your PR

jamiebuilds avatar Oct 26 '18 18:10 jamiebuilds

you're still changing the formatting with indentation

jamiebuilds avatar Oct 26 '18 19:10 jamiebuilds

@jamiebuilds I'm working on it :)

It certainly wasn't my intention to change your formatting. the first commit was through code sandbox and it applied prettier automatically

camflan avatar Oct 26 '18 19:10 camflan

any objection to adding a prettier config to maintain your formatting? I'm happy to get one set up in another PR

camflan avatar Oct 26 '18 19:10 camflan

Sure, could you submit a PR to https://github.com/rehooks/template

jamiebuilds avatar Oct 26 '18 19:10 jamiebuilds

What about receiving the debounce function as an argument?

import { debounce } from 'lodash/fp';
function App() {
  let windowWidth = useWindowWidth();
  let debouncedWindowWidth = useWindowWidth(debounce(500))
    return [
        <pre>Debounced: {JSON.stringify(debouncedWindowWidth)}</pre>,
        <pre>Firehose: {JSON.stringify(windowWidth)}</pre>,
    ]
}

jamesb3ll avatar Oct 29 '18 16:10 jamesb3ll

@jamesb3ll

That could be pretty cool to allow a user to pass a function to apply to the event handler before updating state, then they could pick throttle, debounce, filter, etc, etc. However, I'm not sure lodash/debounce works like that. I think debounce takes a fn as the first arg, delay as second.

We could specify that they give us a function that will take our fn as an arg? Kind of wonky though.


import { debounce as _debounce, throttle as _throttle }  from 'lodash/fp';

let debounce = delay => fn => _debounce(fn, delay)
let throttle = delay => fn => _throttle(fn, delay)

function App() {
  let windowWidth = useWindowWidth();
  let debouncedWindowWidth = useWindowWidth(debounce(500))
  let throttledWindowWidth = useWindowWidth(throttle(500))


    return [
        <pre>Debounced: {JSON.stringify(debouncedWindowWidth)}</pre>,
        <pre>Throttled: {JSON.stringify(throttledWindowWidth)}</pre>,
        <pre>Firehose: {JSON.stringify(windowWidth)}</pre>,
    ]
}

🤷‍♂️

Is there a better way?

camflan avatar Oct 29 '18 18:10 camflan

@camflan the lodash/fp package is for functional programming and should be data last and currying for arguments. No changes should be needed :)

jamesb3ll avatar Oct 29 '18 18:10 jamesb3ll

@camflan @jamesb3ll If you pass a function argument to useWindowWidth you need to memoize the function...otherwise it's different on every render and useWindowWidth has to re-throttle/re-debounce each time.

I mean I guess you could only use the first function ever passed, but that might violate some users' assumption that they can pass a function with a different delay to change throttle/debounce rate.

jedwards1211 avatar Mar 02 '19 02:03 jedwards1211

@camflan to elaborate on what @jamesb3ll said, AFAIK debounce from lodash/fp already has the signature delay => fn => throttledFn. It's the non-fp version that has the signature (fn, delay) => throttledFn. I can't see any other way, at first I thinking a separate hook that wraps the base hook should perform the throttling, but then I realized, even if setWindowSize is throttled, the component will still rerender on every event.

jedwards1211 avatar Mar 02 '19 02:03 jedwards1211