<Debounce /> and <Throttle /> component
pedronauck opened this issue · comments
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>
@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.
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!
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>
Really, good point 🙏
@renatorib Isn't this leaky? Just never tried to fit debounce to render in my mind.
🤔 Yeah, maybe.
I tried here and debounce worked (don't know about perf). But throttle doesn't.
Yep. There should be persistent state for timers.
I tried something at the constructor: https://codesandbox.io/s/kk0190xnk5
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>
I actually wrote a little Debounce component: https://github.com/fea17e86/react-beco. I just realised that this issue was open.
@0maxxam0 funded this issue with $12. Visit this issue on Issuehunt
:-O Write a Debounce and Throttle
component is easy. But the hard point is to decide should we include it in react-powerplug
.
https://github.com/threepointone/react-debounce - this is a pretty good one