DEV Community

Greg Kepler
Greg Kepler

Posted on

React useCallback Improvement Ideas

Hello, I'm trying to improve my react skills and get a better understanding on the linting comments.

Specifically, I have this memoized function searchForResults (via useCallback) and the linter is saying

React Hook useCallback has missing dependencies: 'dataUrlFn', 'getAsyncResults', 'getResults', and 'loadAsync'. Either include them or remove the dependency array. If 'dataUrlFn' changes too often, find the parent component that defines it and wrap that definition in useCallback.

So I have a feeling that I'm missing something as far as best practices and was hoping someone could help give ideas of alternate ways to implement a function like this that updates ONLY when the search query changes.

export const SearchWithAutocomplete: FC<SearchWithAutocompleteProps> = ({
  data,
  dataUrlFn,
  onSelect,
  debounceTimeout = DEFAULT_SEARCH_DEBOUNCE_TIMEOUT,
}) => {
  const ref = useRef<any>();
  const loadAsync: boolean = dataUrlFn != null;

  // state
  const [searchQuery, setSearchQuery] = useState<string>("");
  const [results, setResults] = useState<AutocompleteResults>();
  const [isFocus, setIsFocus] = useState<boolean>(false);

  // hooks
  const debouncedQuery = useDebounce(searchQuery, debounceTimeout);
  const getResults = useAutocomplete({ staticData: data || [] });
  const getAsyncResults = useAsyncAutocomplete();

  // Any ideas how to improve this?
  const searchForResults = useCallback(async () => {
    if (debouncedQuery.length > 0) {
      if (!loadAsync) {
        const searchResults = getResults(debouncedQuery);
        setResults(searchResults);
      } else if (loadAsync && dataUrlFn) {
        const url = dataUrlFn(debouncedQuery);
        const searchResults = await getAsyncResults(url);
        setResults(searchResults);
      }
    } else {
      setResults([]);
    }
  }, [debouncedQuery]);
  /* linter for above shows "React Hook useCallback has missing dependencies: 
'dataUrlFn', 'getAsyncResults', 'getResults', and 'loadAsync'. Either include them or 
remove the dependency array. If 'dataUrlFn' changes too often, find the parent component 
that defines it and wrap that definition in useCallback.*/

  useEffect(() => {
    searchForResults();
  }, [searchForResults]);

  return (
    <InputContainer ref={ref}>
      <Input
        autoComplete="off"
        className="search-autocomplete"
        onChange={(e) => setSearchQuery(e.target.value)}
        type="search"
        value={searchQuery}
      />
      <SearchIcon />
      {results && results.length > 0 && (
        <Results
          onSelect={onSelect}
          results={results}
        />
      )}
    </InputContainer>
  );
};
Enter fullscreen mode Exit fullscreen mode

Also open to any other ideas on how to improve this component.

Thanks in advance.

Top comments (2)

Collapse
 
leandro_nnz profile image
Leandro Nuñez

Perhaps this could help you
stackoverflow.com/a/72762060

Good luck

Collapse
 
garyford profile image
GaryFord

that is great concepts you have shared . king exchange betting