Chris
Chris

Reputation: 993

Executing a click only a certain amount of time without accumulating events

I'm trying to utilize an input field to be saved to the local storage using the native javascript localstorage api (or any react local storage module on npm) but have a little trouble implementing a code where it saves to local storage at a least of 5 seconds interval from the last typed letter.

import React, { Component } from 'react';
import throttle from 'lodash/throttle';

class Something extends Component {
  state = { inputValue: "" };

  handleChange = () => {
    this.changeState();
  }

  changeState = throttle(
    newValue => {
      this.setState({ inputValue: newValue });
      console.log('executed!');
    },
    5000
  );

  render() {
    return (
      <div>
        <input type="text" 
          value={this.state.inputValue} 
          placeholder="Type something here" 
          onChange={this.handleChange} 
        />
      </div>
    );
  }
};

The problem is that the method changeState() successfully executes after 5 seconds but then it gets executed again at once based on how many clicks you spam it with. What is a way to prevent that?

Upvotes: 0

Views: 75

Answers (3)

bennygenel
bennygenel

Reputation: 24680

move your interval to componentDidMount and save this.state.inputValue to the local storage. onChange just set the state value.

import React, { Component } from 'react';
import throttle from 'lodash/throttle';

class Something extends Component {
  state = { inputValue: "", changed: false };

  handleChange = (event) => {
    this.setState({ inputValue: event.target.value, changed: true });
  }

  componentDidMount() {
      this.interval = setInterval(()=> {
          if (this.state.changed === true) {
              // here save to the localStorage this.state.inputValue
              this.setState({ changed: false });
          }
      }, 5000);
  }

  componentWillUnmount() {
      clearInterval(this.interval);
  }

  render() {
    return (
      <div>
        <input type="text" 
          value={this.state.inputValue} 
          placeholder="Type something here" 
          onChange={this.handleChange} 
        />
      </div>
    );
  }
};

Upvotes: 1

Ivan Minakov
Ivan Minakov

Reputation: 1442

You can use lodash debounce() for this.

Upvotes: 1

Joseph Ditton
Joseph Ditton

Reputation: 1028

You want to debounce. When you debounce a function it will only execute the function a certain amount of time after the last time it was called. If it gets called again then the timer resets before it executes. Lodash has a debounce method. You want to debounce the save method by 5000ms and then call the function every time the user changes input, then if they stop typing for 5 seconds, the save will be called. Here are the docs for lodash debounce https://lodash.com/docs/4.17.4#debounce

Upvotes: 3

Related Questions