React hooks doing an infinite fetching when getting data from child but has no problem if the parent is a class component

I have a reusable SearchHeader component that has a controlled input and passes the data from the input to his parents

SearchHeader.js

const SearchHeader = ({ onChangeSearch }) => {
  const [searchValue, setSearchValue] = useState('');

  useEffect(() => {
    const timeoutId = setTimeout(() => {
      onChangeSearch(searchValue);
    }, 400);

    return () => {
      clearTimeout(timeoutId);
    };
  }, [searchValue, onChangeSearch]);
  return (
    <Container>
      <ContainerHead>
        <ContainerInput>
          <IoSearch />
          <div style={{ width: '5px' }}></div>
          <TextInput
            className="TextInput_Search"
            placeholder="Search here..."
            value={searchValue}
            onChange={(evt) => setSearchValue(evt.target.value)}
          />
        </ContainerInput>
        <div style={{ width: '8px' }}></div>
        <Text
          size="12px"
          weight="400"
          color={Token.color.white}
          cursor="pointer"
          onClick={() => history.goBack()}
        >
          Batal
        </Text>
      </ContainerHead>
    </Container>
  );
};

Everything it’s okay when I use this component in-class component to make an API request and set the state for the result

UniversalSearch.js

class UniversalSearch extends Component {
  state = {
    searchResult: [],
  };

  handleSearch = (value) => {
    if (value) {
      universalSearch(value).then((response) => {
        this.setState({ searchResult: response.data });
        console.log(response.data);
      });
    }
  };

  render() {
    return (
      <div>
        <SearchHeader onChangeSearch={this.handleSearch} />
      </div>
    );
  }
}

but when I turn the component into a functional component the handle search won’t stop fetching an API request

export default function UniversalSearch() {
  const [searchResult, setSearchResult] = useState([]);
  const handlesearch = (value) => {
    universalSearch(value).then((response) => {
      setSearchResult(response.data)
      console.log(response.data);
    });

  return (
    <div>
      <SearchHeader onChangeValue={handlesearch}/>
     </div>
  );
}

the infinite fetching only came when I set the state for the searchResult. but in-class component everything working as expected that make me so confused how it is possible?

Answer

This seems to happen because every time you set the state value in the function the component renders and creates a new function.

In order to fix this, you can make use of useCallback.

const handlesearch = useCallback((value) => {
    universalSearch(value).then((response) => {
      setSearchResult(response.data)
      console.log(response.data);
    }), [universalSearch])

Leave a Reply

Your email address will not be published. Required fields are marked *