Overview
The JobListings component is a container that renders a collection of job cards. It handles empty states and automatically renders a JobCard for each job in the provided array.
Usage
import { JobListings } from '@/components'
function SearchPage () {
const jobs = [
{
id: "1" ,
titulo: "Senior React Developer" ,
empresa: "Tech Corp" ,
ubicacion: "Remoto" ,
descripcion: "We are looking for..." ,
data: { modalidad: "remoto" , nivel: "senior" , technology: "react" }
},
// ... more jobs
]
return < JobListings jobs = { jobs } />
}
Props
Array of job objects to display. Each job should match the structure expected by the JobCard component.
Features
Empty State Handling
The component automatically detects when the jobs array is empty and displays a helpful message:
const isEmpty = jobs . length === 0
return (
< div className = { `jobs-listings ${ isEmpty ? 'jobs-listings--empty' : '' } ` } >
{ isEmpty && (
< p style = { { textAlign: 'center' , padding: '1rem' , textWrap: 'balance' } } >
No se han encontrado empleos que coincidan con los criterios de búsqueda.
</ p >
) }
{ /* ... */ }
</ div >
)
Automatic JobCard Rendering
Iterates through the jobs array and renders a JobCard for each item:
{ jobs . map ( job => (
< JobCard key = { job . id } job = { job } />
))}
Component Structure
Full Component
Basic Usage
With Loading State
import { JobCard } from '@/components/JobCard/JobCard.jsx'
export function JobListings ({ jobs }) {
const isEmpty = jobs . length === 0
return (
< div className = { `jobs-listings ${ isEmpty ? 'jobs-listings--empty' : '' } ` } >
{ isEmpty && (
< p style = { { textAlign: 'center' , padding: '1rem' , textWrap: 'balance' } } >
No se han encontrado empleos que coincidan con los criterios de búsqueda.
</ p >
) }
{ jobs . map ( job => (
< JobCard key = { job . id } job = { job } />
)) }
</ div >
)
}
Styling
CSS Classes
The component uses two CSS classes:
jobs-listings - Base container class
jobs-listings--empty - Modifier class applied when the jobs array is empty
Empty State Styling
The empty state message uses inline styles:
style = {{
textAlign : 'center' ,
padding : '1rem' ,
textWrap : 'balance'
}}
Usage Patterns
With Search Filters
import { JobListings , SearchFormSection } from '@/components'
import { useState } from 'react'
function JobSearchPage () {
const [ filteredJobs , setFilteredJobs ] = useState ([])
const handleSearch = ( filters ) => {
// Filter jobs based on search criteria
const results = applyFilters ( allJobs , filters )
setFilteredJobs ( results )
}
return (
<>
< SearchFormSection onSearch = { handleSearch } />
< JobListings jobs = { filteredJobs } />
</>
)
}
import { JobListings , Pagination } from '@/components'
import { useState } from 'react'
function PaginatedJobsPage () {
const [ currentPage , setCurrentPage ] = useState ( 1 )
const jobsPerPage = 10
const startIndex = ( currentPage - 1 ) * jobsPerPage
const endIndex = startIndex + jobsPerPage
const currentJobs = allJobs . slice ( startIndex , endIndex )
return (
<>
< JobListings jobs = { currentJobs } />
< Pagination
currentPage = { currentPage }
totalPages = { Math . ceil ( allJobs . length / jobsPerPage ) }
onPageChange = { setCurrentPage }
/>
</>
)
}
With Loading and Error States
import { JobListings , JobCardSkeleton , ErrorBoundary } from '@/components'
function JobsPageWithStates () {
const { jobs , isLoading , error } = useJobsQuery ()
if ( isLoading ) return < JobCardSkeleton count = { 6 } />
if ( error ) return < div > Error loading jobs </ div >
return (
< ErrorBoundary >
< JobListings jobs = { jobs } />
</ ErrorBoundary >
)
}
Empty State
Default Message
The default empty state message is in Spanish:
“No se han encontrado empleos que coincidan con los criterios de búsqueda.”
Custom Empty State
To customize the empty state, you can create a wrapper component:
function CustomJobListings ({ jobs , emptyMessage }) {
if ( jobs . length === 0 ) {
return (
< div className = "custom-empty-state" >
< p > { emptyMessage || 'No jobs found' } </ p >
</ div >
)
}
return < JobListings jobs = { jobs } />
}
Key Prop
The component uses job.id as the key for each JobCard. Ensure each job has a unique id property to prevent rendering issues.
Large Lists
For very large job lists, consider implementing:
Pagination - Limit the number of jobs displayed per page
Virtual scrolling - Render only visible items
Lazy loading - Load jobs as the user scrolls
Source Code
Location: src/components/JobListings/JobListings.jsx:3
JobCard Individual job card component
Pagination Add pagination to job listings
SearchFormSection Search and filter jobs
Loading Loading skeleton for job cards
Best Practices
Validate job data - Ensure each job object has all required properties
Handle loading states - Show skeleton loaders while fetching data
Implement pagination - Don’t render hundreds of jobs at once
Use ErrorBoundary - Wrap JobListings to catch rendering errors
Provide feedback - The empty state helps users understand why no jobs are shown