a movie search app


findafilm is a movie search app. It uses The MovieDB API to fetch information on new releases, popular films, and user-specified titles. Built with Chakra UI, it offers a simple, clean interface that makes it easy to get the most relevant info about a particular movie.

Findafilm screenshot
Findafilm screenshot
Findafilm screenshot
Findafilm screenshot

Click to enlarge

purpose & goal

The purpose of the project was to gain more exposure to working with a third-party API, as well as to work on using custom React Hooks for handling data fetching in a dynamic way.

Beyond that, I’m also planning to integrate a newer hook-based Redux ToolKit “slice” configuration for state management (findafilm currently uses a more default React Context API). The goal here being to both become more familiar with the newer recommended Redux process as well as improve the project’s structure for scalability.


One of the more helpful features in findafilm is a custom React hook to grab API data and handle errors. The hook takes into account the specific way TMDB data is structured, defines a customtype for that structure, allows for multiple request routes to get data for titles, genres, cast and crew, etc., and has a fallback for loading states and failed responses.

The hook uses axios for data fetching, and helps keeps things consistent when calling out to the API.

export const useMovieFetch = (dataURL: string): IData => { const [data, setData] = useState<DataType>() const [fetchError, setFetchError] = useState<ErrorType>(null) const [isLoading, setIsLoading] = useState<LoadingType>(false) useEffect(() => { let isMounted = true const source = axios.CancelToken.source() const fetchData = async url => { setIsLoading(true) try { const response = await TMDB.get(url, { cancelToken: source.token, }) if (isMounted) { setData( setFetchError(null) } } catch (err: any) { if (isMounted) { setFetchError(err.message) setData({}) } } finally { isMounted && setIsLoading(false) } } fetchData(dataURL) const cleanUp = () => { isMounted = false source.cancel() } return cleanUp }, [dataURL]) return { data, fetchError, isLoading, } }


findafilm is currently in active development.

I intend on adding many more features such as an authentication system creating accounts or signing in with third party services, creating a watchlist feature to keep track of movies to watch, a more robust search ability (top genre films, search by decade, read reviews, etc), and more complex linking between one film and another (e.g., clicking a cast member to search for other films they're in, etc).

I also plan to implement a modern Redux ToolKit integration for state management for greater scalability.

lessons learned

I’ve learned a lot about dealing with asynchronous data while building findafilm, especially in regards to having robust fallbacks for loading/error states. The useMovieFetch hook includes all these features when making an API request to TMDB, and in turn it passes loading and success states to other parts of the application as needed.

Similarly, the header text for search results renders dynamically based on both loading states and whether a search is performed with a user-defined term or from predefined criteria like "Top-rated Movies" or "Most Popular Movies".

This has helped me to better understand creating multiple layers of consistency for an application, and account for edge cases and unexpected responses with anticipatory fallbacks, resulting in fewer errors and a more reliable experience.

back to home