Typescript IMDB

DEMO
SearchMovieDB.tsx

SearchBar.tsx
interface Movie {
  title: string;
  year: string;
  poster: string;
  imdbID: string;
}

function TypescriptDemo() {
  const [movie, setMovie] = React.useState<Movie | null>(null);
  const [query, setQuery] = React.useState("");
  const [error, setError] = React.useState("");

  const defaultMovies = [
    "tt1160419",
    "tt4633694",
    "tt2953050",
    "tt5180504",
    "tt0266543",
    "tt8398600",
    "tt0110357",
  ];
  // get a number from 0 to final index of movies array
  const randMov = Math.floor(Math.random() * defaultMovies.length);

  React.useEffect(() => {
    // fetch a random movie from the defaultMovies list
    const fetchMovieById = async () => {
      const res = await fetch(
        `http://www.omdbapi.com/?i=${defaultMovies[randMov]}&apikey=${process.env.REACT_APP_OMDB_API_KEY}`
      );
      const data = await res.json();
      setMovie({
        title: data.Title,
        year: data.Year,
        poster: data.Poster,
        imdbID: data.imdbID,
      });
    };

    try {
      fetchMovieById();
    } catch (err) {
      console.log(err);
    }
  }, []);

  const handleSearch = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setError("");
    setMovie(null);
    try {
      const data = await searchMovie(query);
      if (data.Response === "True") {
        const firstResult = data.Search[0];
        setMovie({
          title: firstResult.Title,
          year: firstResult.Year,
          poster: firstResult.Poster,
          imdbID: firstResult.imdbID,
        });
      } else {
        setError(data.Error);
        setMovie(null);
      }
    } catch (err) {
      console.log(err);
    }
  };

  const renderContent = () => {
    if (error !== "")
      return (
        <ErrorCont>
          <img src={NoDataImg} alt="" width="200px" />
          <p>{error}</p>
        </ErrorCont>
      );
    else if (movie === null)
      return (
        <>
          <SkeletonCard />
          <SkeletonInfo />
        </>
      );
    else
      return (
        <a
          href={`https://www.imdb.com/title/${movie.imdbID}/`}
          target="_blank"
          rel="noopener noreferrer"
        >
          <Poster src={movie.poster} />
        </a>
        <InfoBar>
          <div>{movie.title}</div>
          <YearWrapper>{movie.year}</YearWrapper>
        </InfoBar>
      );
  };

  return (
    <>
      {renderContent()}
      <form action="" onSubmit={handleSearch}>
        <SearchBar
          value={query}
          onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
            setQuery(event.currentTarget.value);
          }}
          placeholder="Search for a movie..."
        />
      </form>
    </>
  );
}

const searchMovie = async (query: string) => {
  // if query is empty, replace with a letter to give the
  // 'too many results' error
  const res = await fetch(
    `http://www.omdbapi.com/?s=${query ? query : "s"}&apikey=${
      process.env.REACT_APP_OMDB_API_KEY
    }`
  );
  const data = await res.json();
  return data;
};

Note: Code snippets do not include styling details unless they are the focus of the exercise.

Copyright © 2022 Explore React