Joao Victor Menom
Joao Victor Menom

Reputation: 13

clearTimeout is not working on React Native

I am set up a Timeout for when the user stops typing for 3 seconds an api call is made and the ActivityIndicator appears.

edited with full code:

import React, { useState, useEffect } from 'react';
import { Text } from 'react-native';
import { ActivityIndicator } from 'react-native';

import {
  Container,
  SearchBar,
  SearchBarInput,
  SearchLoading,
  SearchResultList,
  Product,
} from './styles';

import api from '../../services/api';

export default function Search() {
  const [searchResult, setSearchResult] = useState([]);
  const [searchText, setSearchText] = useState('');
  const [searching, setSearching] = useState(false);
  const [focused, setFocused] = useState(false);

  function renderProduct({ item }) {
    return <Text>Oi</Text>;
  }

  let timer;

  function handleChangeText(text) {
    setSearching(false);
    setSearchText(text);

    clearTimeout(timer);

    timer = setTimeout(() => setSearching(true), 3000);
  }

  useEffect(() => {
    async function search() {
      const response = await api.get(`products?search=${searchText}`);

      setSearchResult(response.data);
      setSearching(false);
    }
    if (searching) {
      search();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [searching]);

  return (
    <Container>
      <SearchBar focused={focused}>
        <SearchBarInput
          placeholder="Pesquisar..."
          onChangeText={handleChangeText}
          onFocus={() => setFocused(true)}
          onBlur={() => setFocused(false)}
          value={searchText}
        />
        {searching && (
          <SearchLoading>
            <ActivityIndicator size="small" color="#000" />
          </SearchLoading>
        )}
      </SearchBar>
      <SearchResultList
        data={searchResult}
        keyExtractor={item => String(item.id)}
        renderItem={renderProduct}
      />
    </Container>
  );
}

..............................................

But it's not working as it should:

https://user-images.githubusercontent.com/54718471/69919848-14680a00-1460-11ea-9047-250251e42223.gif

Upvotes: 1

Views: 942

Answers (1)

azundo
azundo

Reputation: 6052

Remember that the body of the function is run on every single render. So the reference to the existing timer is lost each time the component re-renders.

You can use the useRef hook (https://reactjs.org/docs/hooks-reference.html#useref) to keep a stable reference across renders.

const timerRef = useRef(null);

function handleChangeText(text) {
  setSearching(false);
  setSearchText(text);

  clearTimeout(timerRef.current);

  timerRef.current = setTimeout(() => setSearching(true), 3000);
}

Upvotes: 3

Related Questions