Throttling dispatch in redux producing strange behaviour

- 1 answer

Ad

I have this class:

export default class Search extends Component {

    throttle(fn, threshhold, scope) {
       var last,
           deferTimer;
       return function () {
            var context = scope || this;
            var now = +new Date,
           args = arguments;
           if (last && now < last + threshhold) {
            // hold on to it
               clearTimeout(deferTimer);
               deferTimer = setTimeout(function () {
                   last = now;
                   fn.apply(context, args);
               }, threshhold);
           } else {
               last = now;
               fn.apply(context, args);
           }
       }
    }

    render() {
        return (
          <div>
            <input type='text' ref='input' onChange={this.throttle(this.handleSearch,3000,this)} />
          </div>
        )
    }

    handleSearch(e) {
        let  text = this.refs.input.value;
        this.someFunc();
        //this.props.onSearch(text)
    } 

    someFunc() {
        console.log('hi')
    }
}

All this code does it log out hi every 3 seconds - the throttle call wrapping the handleSearch method takes care of this

As soon as I uncomment this line:

this.props.onSearch(text)

the throttle methods stops having an effect and the console just logs out hi every time the key is hit without a pause and also the oSearch function is invoked.

This onSearch method is a prop method passed down from the main app:

<Search onSearch={ text => dispatch(search(text)) } /> 

the redux dispatch fires off a redux search action which looks like so:

export function searchPerformed(search) {
    return {
        type: SEARCH_PERFORMED
    }
}

I have no idea why this is happening - I'm guessing it's something to do with redux because the issue occurs when handleSearch is calling onSearch, which in turn fires a redux dispatch in the parent component.

Ad

Answer

Ad

Thanks to luanped who helped me realise the issue here. With that understood I was able to find a simple solution. The search component does not need to update as the input is an uncontrolled component. To stop the cyclical issue I was having I've used shouldComponentUpdate to prevent it from ever re-rendering:

constructor() {
   super();
   this.handleSearch = _.throttle(this.handleSearch,1000);
}

shouldComponentUpdate() {
    return false;
}

I also moved the throttle in to the constructor so there can only ever be once instance of the throttle.

I think this is a good solution, however I am only just starting to learn react so if anyone can point out a problem with this approach it would be welcomed.

Ad
source: stackoverflow.com
Ad