Home > Back-end >  RTK Query run query only after user stops typing in search field
RTK Query run query only after user stops typing in search field

Time:06-05

I'm a little bit confused about using useEffect,useCallback and running RTK Queries. What I'm trying to achieve is users would be able to search movies based on an input field provided in the app.

There is a Home Page with an input field for users to search for movies. also, I have a useSearchMovieQuery in RTK Query API which search for whatever user enters in the search field. I want to prevent the query from running on the initial render, which can be achieved by skipping the query using "skip" or "skipToken".

I want only to run this query after the user stops typing, not immediately after onChange event in the search field.

here is what I've tried so far.

const Home = () => {
  const [page, setPage] = useState<number>(1);
  const [skip, setSkip] = useState<boolean>(true);
  const [searchQuery, setSearchQuery] = useState<string>("");
  const { data: popularMovies, isLoading: popularLoading } =
    useGetPopularMoviesQuery(page);
  const { data: topRatedMovies, isLoading: topRatedLoading } =
    useGetTopRatedMoviesQuery();
  const { data: upcomingMovies, isLoading: upcomingLoading } =
    useGetUpcomingMoviesQuery();
  const {
    data: searchResult,
    isSuccess: searchedForMovie,
    isFetching,
    isError,
  } = useSearchMovieQuery(searchQuery, { skip });
  const handleOnChangePage = (e: unknown, value: number) => {
    setPage(value);
  };
  const handleSearch = (
    event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    setSearchQuery(event.currentTarget.value);
    setSkip((prev) => !prev);
  };

  return (
    <>
      <div className="category-box container">
        <div className="section mb-3">
          <FormControl fullWidth sx={{ m: 1 }}>
            <OutlinedInput
              id="outlined-adornment-amount"
              placeholder="Search Movies..."
              value={searchQuery}
              onChange={handleSearch}
            />
          </FormControl>
          {searchedForMovie && (
            <SearchResult>
              <MoviesList moviesType={searchResult.results} />
            </SearchResult>
          )}
</>

the confusing thing is that I want to set skip to true for starting the query search, and also only run this after user stops typing. maybe using setTimeout?

the state I'm using for skip query is:

const [skip, setSkip] = useState<boolean>(true);

the state I'm using for user search query is:

  const [searchQuery, setSearchQuery] = useState<string>("");

and the handleSearch function which runs onChange event for the input is:

      const handleSearch = (
    event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    setSearchQuery(event.currentTarget.value);
    setSkip((prev) => !prev);
  };

that setSkip in the handle search function is one of the problems I know so far that shouldn't be there :D

any helps?

CodePudding user response:

I would use something like useDebounce

const [searchQuery, setSearchQuery] = useState<string>("");
const debouncedSearchQuery = useDebounce(searchQuery, 500);
  const {
    data: searchResult,
    isSuccess: searchedForMovie,
    isFetching,
    isError,
  } = useSearchMovieQuery(debouncedSearchQuery, { skip: debouncedSearchQuery == "" });

This way you will only search when the searchQuery has not changed in the last 500ms and when it is not the empty string.

  • Related