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])