PeliculaGrid
The PeliculaGrid component creates a responsive grid layout for displaying multiple movie cards. It handles loading states and empty results automatically.
Component Overview
import PeliculaGrid from './components/PeliculaGrid' ;
function PeliculasPage () {
const [ peliculas , setPeliculas ] = useState ([]);
const [ loading , setLoading ] = useState ( true );
return (
< PeliculaGrid
peliculas = { peliculas }
loading = { loading }
/>
);
}
Props
Array of movie objects to display in the grid Each movie object should contain:
id (number) - Unique identifier
title (string) - Movie title
year (number) - Release year
duration (number) - Duration in minutes
rating (number) - Rating out of 10
image (string) - Poster image URL
trailerUrl (string) - YouTube embed URL
Loading state indicator. When true, displays a loading spinner instead of the grid.
States Handled
The component automatically handles three different states:
Loading
Empty Results
Movies Display
When loading={true}, displays the LoadingSpinner component: if ( loading ) {
return < LoadingSpinner /> ;
}
When no movies are found, displays an empty state message: if ( ! peliculas || peliculas . length === 0 ) {
return (
< div className = "pelicula-grid__empty" >
< p className = "pelicula-grid__empty-text" > No se encontraron películas </ p >
</ div >
);
}
When movies are available, renders them in a grid: return (
< div className = "pelicula-grid" >
{ peliculas . map ( pelicula => (
< PeliculaCard key = { pelicula . id } pelicula = { pelicula } />
)) }
</ div >
);
Usage Examples
Basic Usage
import { useState , useEffect } from 'react' ;
import PeliculaGrid from './components/PeliculaGrid' ;
import { mockPeliculas } from './data/mockPeliculas' ;
function HomePage () {
const [ featuredPeliculas , setFeaturedPeliculas ] = useState ([]);
const [ loading , setLoading ] = useState ( true );
useEffect (() => {
const timer = setTimeout (() => {
setFeaturedPeliculas ( mockPeliculas . slice ( 0 , 4 ));
setLoading ( false );
}, 500 );
return () => clearTimeout ( timer );
}, []);
return (
< div >
< h2 > Películas Destacadas </ h2 >
< PeliculaGrid peliculas = { featuredPeliculas } loading = { loading } />
</ div >
);
}
From: src/pages/PrincipalPage.jsx:30
With Search and Filters
import PeliculaGrid from './components/PeliculaGrid' ;
import SearchBar from './components/SearchBar' ;
import CategoryFilter from './components/CategoryFilter' ;
import usePeliculaSearch from './hooks/usePeliculaSearch' ;
function PeliculasPage () {
const {
searchTerm ,
setSearchTerm ,
selectedCategory ,
setSelectedCategory ,
filteredPeliculas ,
loading ,
categories
} = usePeliculaSearch ();
return (
< div className = "peliculas-page" >
< h1 > Catálogo de Películas </ h1 >
< div className = "peliculas-page__filters" >
< SearchBar
searchTerm = { searchTerm }
onSearchChange = { setSearchTerm }
/>
< CategoryFilter
categories = { categories }
selectedCategory = { selectedCategory }
onCategoryChange = { setSelectedCategory }
/>
</ div >
< p > { filteredPeliculas . length } películas encontradas </ p >
< PeliculaGrid peliculas = { filteredPeliculas } loading = { loading } />
</ div >
);
}
From: src/pages/PeliculasPage.jsx:18
Full Component Code
Location: src/components/PeliculaGrid.jsx:1
import React from 'react' ;
import PeliculaCard from './PeliculaCard' ;
import LoadingSpinner from './LoadingSpinner' ;
const PeliculaGrid = ({ peliculas , loading }) => {
if ( loading ) {
return < LoadingSpinner /> ;
}
if ( ! peliculas || peliculas . length === 0 ) {
return (
< div className = "pelicula-grid__empty" >
< p className = "pelicula-grid__empty-text" > No se encontraron películas </ p >
</ div >
);
}
return (
< div className = "pelicula-grid" >
{ peliculas . map ( pelicula => (
< PeliculaCard key = { pelicula . id } pelicula = { pelicula } />
)) }
</ div >
);
};
export default PeliculaGrid ;
Responsive Behavior
The grid layout is controlled by CSS and automatically adapts to different screen sizes:
.pelicula-grid {
display : grid ;
grid-template-columns : repeat ( auto-fill , minmax ( 250 px , 1 fr ));
gap : 2 rem ;
}
This creates:
Desktop : 4-5 columns
Tablet : 2-3 columns
Mobile : 1-2 columns
Key Props
Always use unique key props when mapping over movies:
{ peliculas . map ( pelicula => (
< PeliculaCard key = { pelicula . id } pelicula = { pelicula } />
))}
This ensures React can efficiently update the DOM when the movie list changes.
Conditional Rendering
The component short-circuits rendering when loading or empty, preventing unnecessary work:
if ( loading ) return < LoadingSpinner /> ;
if ( ! peliculas ?. length ) return < EmptyState /> ;
return < Grid /> ;
Styling
The component uses these BEM classes:
.pelicula-grid - Main grid container
.pelicula-grid__empty - Empty state container
.pelicula-grid__empty-text - Empty state message
PeliculaCard Individual movie card component rendered in the grid
SearchBar Often used above the grid for filtering movies
CategoryFilter Category dropdown for filtering grid contents