Search code examples
javascriptreactjsreact-hooksinfinite-scrollintersection-observer

react js infinite scroll without third party library


Hi I'm new to react js and would like to implement infinite scroll without any help of third party/library. I achieved the infinite scroll, but there is problem. The problem is that for example my initial search is ant man movie, and then I try to search new movie let say the hulk. It doesn't re-render, but instead it continue/goes under ant man movies. What I want to achieve is to only shows the movie I search. Hopefully my question and problem is understandable.

Below is my code:

import React, { useEffect, useState, useRef, useCallback } from "react";
import axios from "axios";

const my_key = process.env.REACT_APP_MY_KEY;

export const InfiniteScroll = () => {
  const [movies, setMovies] = useState([]);
  const [movieName, setMovieName] = useState("ant man");
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState("");
  const [hasMore, setHasMore] = useState(false);

  useEffect(() => {
     let cancel;
     axios({
        method: "GET",
        url: "http://www.omdbapi.com/",
        params: { apikey: `${my_key}`, s: movieName, page: page },
        cancelToken: new axios.CancelToken((c) => (cancel = c)),
     })
     .then(({ data }) => {
        if (data.Response === "True") {
           setMovies((prev) => [...prev, ...data.Search]);
           setHasMore(data.Search.length > 0);
        } else {
           setMovies((prev) => prev);
        }
     })
     .catch((err) => err);
    return () => cancel();
   }, [movieName, page]);

 const myObserver = useRef();
 const myRef = useCallback(
    (node) => {
      if (myObserver.current) myObserver.current.disconnect();
      myObserver.current = new IntersectionObserver((entries) => {
         if (entries[0].isIntersecting && hasMore) {
            setPage((prev) => prev + 1);
         }
      });
      if (node) myObserver.current.observe(node);
      },
     [hasMore]
    );

 const onSubmit = (e) => {
    e.preventDefault();
    setMovieName(search);
    setSearch("");
    setPage(1);
  };

 return (
   <>
     <h1>Searh Movie</h1>
     <form onSubmit={onSubmit}>
       <input
          type="text"
          placeholder="title"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
       />
       <input
          type="submit"
          value="submit"
          disabled={search === "" ? true : false}
        />
     </form>
       {movies === "False" ? (
         <div>
           <h1>No Data</h1>
         </div>
        ) : (
         movies.map(({ imdbID, Title, Year, Poster }, i) => (
           <div key={imdbID + i} ref={myRef}>
              <img src={Poster} alt={imdbID} />
              <h2>{Title}</h2>
             <h3>{Year}</h3>
          </div>
        ))
      )}
     </>
   );
 };

After the most bottom of ant man movie, comes the hulk movie. It should be re render and only shows hulk movie.

enter image description here


Solution

  • issue solved by seting setMovies([]) empty after search new movies