Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Debounce /> and <Throttle /> component #134

Open
pedronauck opened this issue Jul 3, 2018 · 13 comments
Open

<Debounce /> and <Throttle /> component #134

pedronauck opened this issue Jul 3, 2018 · 13 comments

Comments

@pedronauck
Copy link
Collaborator

pedronauck commented Jul 3, 2018

Everytime that we need to make a debounce or a throttle on some method the process is very annoying. I think that maybe this two components can be useful:

Debounce

<Debounce method={() => console.log('helo')} timer={200}>
  {({ fn }) => /* ... */}
</Debounce>

Throttle

<Throttle method={() => console.log('helo')} timer={200}>
  {({ fn }) => /* ... */}
</Throttle>
@renatorib renatorib self-assigned this Jul 5, 2018
@renatorib
Copy link
Owner

renatorib commented Jul 11, 2018

@pedronauck can you show me a use case? In all use cases I can think I can solve by just using a debounce/throttle fn. A component might be an overkill in these cases.

@pedronauck
Copy link
Collaborator Author

Really, just using a debounce/throttle method like a lodash helper solve the problem. The point is to be able to do that without any other dependency. I can have some state on my component just by using a class component, but using your <State> is more quick and easy. In my head, you can implement your own debounce throttle and give us this power without dependencies too!

@renatorib
Copy link
Owner

I got yout point, but I think its more simpler to manage your debounce/throttle by yourself:

import { Value, Debounce } from 'react-powerplug'

<Value>
  {text => (
    <Debounce fn={text.set} wait={200}>
      {({ fn }) => (
        <input value={text.value} onChange={e => fn(e.target.value)} />
      )}
    </Debounce>
  )}
</Value>

vs.

import { Value } from 'react-powerplug'
import debounce from 'lodash.debounce'

<Value>
  {text => {
    const setText = debounce(text.set, 200)
    return <input value={text.value} onChange={e => setText(e.target.value)} />
  }}
</Value>

@pedronauck
Copy link
Collaborator Author

Really, good point 🙏

@TrySound
Copy link
Collaborator

@renatorib Isn't this leaky? Just never tried to fit debounce to render in my mind.

@renatorib
Copy link
Owner

🤔 Yeah, maybe.

I tried here and debounce worked (don't know about perf). But throttle doesn't.

@TrySound
Copy link
Collaborator

Yep. There should be persistent state for timers.

@renatorib
Copy link
Owner

I tried something at the constructor: https://codesandbox.io/s/kk0190xnk5

@xialvjun
Copy link

xialvjun commented Jul 12, 2018

As to Debounce or Throttle, I think LifeCycle is much more common:

like in https://github.com/xialvjun/xialvjun.github.io/blob/master/_posts/2018-05-22-react-render-props.md

<LifeCycle
  props={{ list }}
  getDerivedStateFromProps={(props, state) => {
    const plist = props.list,
          slist = state.list;
    if (plist.length > slist.length) {
      return {
        list: plist.map(pit => 
          slist.findIndex(sit => sit.id===pit.id) > -1 ?
            pit :
            { ...pit, just_insert: true }
        )
      }
    }
    if (plist.length < slist.length) {
      return {
        list: slist.map(sit =>
          slist.find(pit => sit.id===pit.id) ||
          { ...sit, just_remove: true }
        )
      }
    }
    return props;
  }}
  componentDidUpdate={(prevProps, prevState, snapshot, instance) => {
    setTimeout(() => {
      instance.setState(state => ({ list: state.list.filter(it => !it.just_insert && !it.just_remove) }));
    }, 300);
  }}
>
  {state => state.list.map(it => (
    <div key={it.id} className={`${it.just_insert ? 'inserting' : ''} ${it.just_remove ? 'removing' : ''}`}>
      content
    </div>
  ))}
</LifeCycle>

So, a Debounce is just:

<LifeCycle
  props={{ list }}
  shouldComponentUpdate={(nextProps, nextState, instance) => nextState !== instance.state}
  componentWillReceiveProps={(nextProps, instance) => {
    clearTimeout(instance.debounce_timeout);
    instance.debounce_timeout = setTimeout(() => instance.setState(nextProps), 300);
  }}
>
  {state => xxx}
</LifeCycle>

@fea17e86
Copy link

fea17e86 commented Aug 13, 2018

I actually wrote a little Debounce component: https://github.com/fea17e86/react-beco. I just realised that this issue was open.

@IssueHuntBot
Copy link

@0maxxam0 funded this issue with $12. Visit this issue on Issuehunt

@xialvjun
Copy link

xialvjun commented Oct 1, 2018

:-O Write a Debounce and Throttle component is easy. But the hard point is to decide should we include it in react-powerplug.

@viczam
Copy link

viczam commented Dec 27, 2018

https://github.com/threepointone/react-debounce - this is a pretty good one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants