Skip to main content

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

jobs
array
required
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

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} />
    </>
  )
}

With Pagination

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} />
}

Performance Considerations

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:
  1. Pagination - Limit the number of jobs displayed per page
  2. Virtual scrolling - Render only visible items
  3. 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

  1. Validate job data - Ensure each job object has all required properties
  2. Handle loading states - Show skeleton loaders while fetching data
  3. Implement pagination - Don’t render hundreds of jobs at once
  4. Use ErrorBoundary - Wrap JobListings to catch rendering errors
  5. Provide feedback - The empty state helps users understand why no jobs are shown

Build docs developers (and LLMs) love