handsome
handsome

Reputation: 2432

Execute function in React when user stops typing

I want to execute a function (query a search service) when use stops typing (or hits enter) I saw some examples using lodash Debounce

I´m playing with react hooks and wanted to see if is possible to achieve this without any external libraries.

import React, { useState } from 'react';
import Api from './Api'

const Search = (props) => {

    const [keyword, setKeyword] = useState();
    const [results, setResults] = useState([]);

    let timeout;

    const handleSearch = (event) => {

        setKeyword(event.target.value);

        if (timeout) {
            clearTimeout(timeout);
        }

        timeout = setTimeout(() => {
            timeout = null;

            if (keyword) {
                callSearchService()
            }
        }, 1000);
    }

    const callSearchService = () => {
        Api.search(keyword)
            .then(
                results => setResults(results),
                error => console.log(error)
            )
    }

    return (
        <input type="search" onKeyUp={(e) => handleSearch(e)} />
    )

}

the execution is being delayed by 1000ms but then the function is called one time per character (except for the last character. that´s not being executed, I tried using onChange instead of onKeyUp, but same issue). i probably put the timeout in the wrong place. thanks for your infinite wisdom

Upvotes: 2

Views: 2595

Answers (1)

Nick
Nick

Reputation: 16606

Definitely! You can implement your own debounce functionality using useEffect and useState. In this example, the value is your user input and the code inside the setTimeout callback will only execute when value hasn't changed after 1 second.

const [value, setValue] = useState("");

useEffect(() => {
  const callSearchService = () => {
    Api.search(value)
      .then(
        results => setResults(results),
        error => console.log(error)
      )
  }

  let debouncer = setTimeout(() => {
    callSearchService();
  }, 1000);
  return () => {
    clearTimeout(debouncer);
  }
}, [value]);

What's really important here is the "cleanup" function that clears the timeout if value changes. If 1 second actually passes without any value changes, the code inside your setTimeout callback function will actually execute.

Upvotes: 6

Related Questions