An in-depth guide to the key files of the MovieFlix React Native application and their interplay.
This diagram shows how pages, components, hooks, and services interact to fetch and display movie data.
flowchart LR
IndexPage["HomeTab index tsx"] --> SearchBarComp["SearchBar component"]
IndexPage --> MovieCardComp["MovieCard component"]
SearchPage["SearchTab search tsx"] --> SearchBarComp
SearchPage --> MovieCardComp
MovieCardComp --> DetailsPage["MovieDetails id tsx"]
SearchBarComp --> UseFetchHook["useFetch hook"]
UseFetchHook --> APIService["API service api ts"]
APIService --> TMDB["TMDB API"]
A Home Tab screen that fetches and lists the latest popular movies.
This file renders the main tab of the app. It calls the TMDB API to retrieve popular movies and displays them in a grid.
- Automatically fetch movies on mount.
- Show loading indicator or error message.
- Render a search bar that navigates to the search tab.
- Display movies using a grid of
MovieCardcomponents.
useFetchhook for data fetching.fetchMoviesservice for API calls.SearchBar,MovieCardcomponents.iconsandimagesconstants.useRouterfromexpo-router.
const { data: movies, loading, error } = useFetch(
() => fetchMovies({ query: '' })
);
...
<View className="flex-1 bg-primary">
<Image source={images.bg} className="absolute w-full" />
<ScrollView ...>
<SearchBar
onPress={() => router.push('/search')}
placeholder="Search for a Movie"
/>
<FlatList
data={movies}
renderItem={({ item }) => <MovieCard {...item} />}
numColumns={3}
keyExtractor={item => item.id.toString()}
/>
</ScrollView>
</View>A Search Tab allowing users to search movies by title with debounce and trending count updates.
This screen provides a text input for movie search. It performs debounced queries and logs usage counts.
- Manage
searchQuerystate. - Debounce API calls on query change.
- Display loading spinner and error messages.
- List matching movies using
MovieCard.
useFetchhook (manual fetch mode).fetchMoviesservice.updateSearchCount(tracks trending searches).SearchBar,MovieCardcomponents.icons,imagesfor branding.
const { data: movies = [], loading, error, refetch, reset } =
useFetch(() => fetchMovies({ query: searchQuery }), false);
useEffect(() => {
const id = setTimeout(async () => {
if (searchQuery.trim()) {
await refetch();
if (movies.length) {
await updateSearchCount(searchQuery, movies[0]);
}
} else reset();
}, 500);
return () => clearTimeout(id);
}, [searchQuery]);A Saved Tab placeholder for displaying user-saved movies.
Currently renders static text. Intended to list movies the user has saved or favorited.
export default function Saved() {
return (
<View>
<Text>saved</Text>
</View>
);
}A Profile Tab placeholder for user profile information.
Renders static profile text. Future enhancements may include user settings and details.
export default function Profile() {
return (
<View>
<Text>profile</Text>
</View>
);
}A Movie Details dynamic route to display detailed info for a selected movie.
Stub for the movie details page. Meant to fetch and render full details based on id route parameter.
export default function MovieDetails() {
return (
<View>
<Text>MovieDetails</Text>
</View>
);
}A custom button component with consistent styling.
Wraps TouchableOpacity and forwards a ref. Accepts all touch props and a title.
title: string— Button label.- All
TouchableOpacityProps.
<Button title="Click me" onPress={handlePress} />- Rounded, indigo background.
- Shadow and padding.
- White, centered text.
A SafeAreaView wrapper to ensure content respects device safe areas.
Provides consistent margin and flex styling for screen layouts.
<Container>
{/* screen content */}
</Container>flex-1 m-6for uniform spacing.
Displays development hints for editing the current screen.
Shows the file path and instructions for hot-reload on code changes.
path: string— File path to display.
Often used inside ScreenContent to annotate screens.
Renders a movie poster card in grid views.
Displays poster image, title, rating stars, and release year. Wraps content in a navigable Link.
id,poster_path,title,vote_average,release_date.
<MovieCard
id={movie.id}
poster_path={movie.poster_path}
title={movie.title}
vote_average={movie.vote_average}
release_date={movie.release_date}
/>- Falls back to placeholder image if
poster_pathis missing. - Rounds rating to a 5-star scale.
- Links to
/movies/id.
A template wrapper for screens with title and code info.
Centers content vertically and horizontally. Inserts a title, separator, and EditScreenInfo.
title: stringpath: stringchildren?: React.ReactNode
<ScreenContent title="Home" path="app/(tabs)/index.tsx">
{/* custom JSX */}
</ScreenContent>A search input component with icon and styling.
Shows a search icon and a TextInput. Supports placeholder and press handler.
placeholder: stringonPress?: () => void
<SearchBar
placeholder="Search for movies"
onPress={() => console.log('Pressed')}
/>Exports key/value pairs of icon assets.
| Key | Asset Path |
|---|---|
| home | @/assets/icons/home.png |
| search | @/assets/icons/search.png |
| person | @/assets/icons/person.png |
| logo | @/assets/icons/logo.png |
| save | @/assets/icons/save.png |
| star | @/assets/icons/star.png |
| play | @/assets/icons/play.png |
| arrow | @/assets/icons/arrow.png |
Exports key/value pairs of background and decorative images.
| Key | Asset Path |
|---|---|
| bg | @/assets/images/bg.png |
| highlight | @/assets/images/highlight.png |
| rankingGradient | @/assets/images/rankingGradient.png |
TypeScript interfaces defining core data shapes.
- Movie: Basic movie info returned by TMDB.
- TrendingMovie: Tracks search term, count, and poster URL.
- MovieDetails: Full details including collections, companies, etc.
- TrendingCardProps: Props for a trending search card (
movie,index).
Service functions for interacting with The Movie Database API.
export const TMDB_CONFIG = {
BASE_URL: "https://api.themoviedb.org/3",
API_KEY: process.env.EXPO_PUBLIC_MOVIE_API_KEY,
headers: {
accept: "application/json",
Authorization: `Bearer ${process.env.EXPO_PUBLIC_MOVIE_API_KEY}`,
},
};- Accepts
{ query: string }. - If
querynon-empty, calls/search/movie; else/discover/movie. - Returns
Promise<Movie[]>. - Throws on non-OK response.
- Accepts a
movieIdstring. - Calls
/movie/{movieId}endpoint. - Returns
Promise<MovieDetails>.
sequenceDiagram
Component->>APIService: fetchMovies(query)
APIService->>TMDB: GET /search/movie or /discover/movie
TMDB-->>APIService: JSON results
APIService-->>Component: Movie[]
A custom React hook to streamline async data fetching.
function useFetch<T>(
fetchFunction: () => Promise<T>,
autoFetch?: boolean
): {
data: T | null;
loading: boolean;
error: Error | null;
refetch: () => Promise<void>;
reset: () => void;
};- Manages
data,loading,errorstate. - Calls
fetchFunctionon mount ifautoFetchistrue. - Exposes
refetchandreset.
flowchart TD
Component --> useFetch
useFetch --> fetchFunction
fetchFunction --> API
API --> useFetch
useFetch --> Component
Enables importing .png files as modules in TypeScript.
declare module "*.png" {
const content: any;
export default content;
}Expo configuration file defining app metadata and platform settings.
{
"expo": {
"name": "MovieFlix",
"slug": "MovieFlix",
"version": "1.0.0",
"scheme": "movie",
"platforms": ["ios", "android"],
"plugins": ["expo-router"],
"experiments": { "typedRoutes": true, "tsconfigPaths": true },
"orientation": "portrait",
"icon": "./assets/images/logo.png",
"splash": { "image": "./assets/images/logo.png" },
"assetBundlePatterns": ["**/*"]
}
}Defines project scripts, dependencies, and tooling for MovieFlix.
{
"name": "movie",
"version": "1.0.0",
"main": "expo-router/entry",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"lint": "eslint \"**/*.{js,ts,tsx}\" && prettier -c",
"format": "eslint --fix && prettier --write"
},
"dependencies": {
"expo": "^54.0.0",
"expo-router": "~6.0.17",
"react": "19.1.0",
"react-native": "0.81.5",
"nativewind": "latest",
"@expo/vector-icons": "^15.0.2"
},
"devDependencies": {
"typescript": "~5.9.2",
"eslint": "^9.25.1",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11"
}
}