Hone logo
Hone
Problems

React Image Gallery with Filtering and Pagination

Building an image gallery is a common requirement in web applications. This challenge asks you to implement a React-based image gallery that displays a list of images, allows users to filter them by category, and provides pagination for handling large datasets. This exercise will test your understanding of React components, state management, props, and handling user interactions.

Problem Description

You are tasked with creating a React component that displays a collection of images. Each image should have a URL, a title, and a category. The gallery should:

  1. Display Images: Render each image with its title and URL (displayed as an <img> tag).
  2. Filtering: Provide a dropdown menu allowing users to filter images by category. The dropdown should list all unique categories present in the image data. When a category is selected, only images belonging to that category should be displayed. An "All Categories" option should be present, displaying all images.
  3. Pagination: Implement pagination to handle a large number of images. Display a set number of images per page (e.g., 10 images per page). Provide "Previous" and "Next" buttons to navigate between pages. The current page number should be displayed.
  4. Loading State: Display a loading indicator while the image data is being fetched (simulated in this case).
  5. Error Handling: Display an error message if the image data fails to load.

Key Requirements:

  • Use functional components and TypeScript.
  • Manage state for the images, current category, and current page.
  • Handle user interactions (dropdown selection, pagination clicks).
  • Ensure the UI updates correctly based on state changes.
  • The image data should be fetched from a simulated API (see mockImageData).

Expected Behavior:

  • Initially, all images should be displayed, and the category dropdown should show "All Categories" selected.
  • Selecting a category from the dropdown should filter the images accordingly.
  • Clicking "Previous" should navigate to the previous page.
  • Clicking "Next" should navigate to the next page.
  • The number of images displayed per page should be consistent.
  • Loading and error states should be clearly indicated to the user.

Examples

Example 1:

Input: mockImageData (as defined below)
Output: All 20 images displayed, category dropdown showing "All Categories" selected, pagination showing page 1 of 2.
Explanation: The gallery initially loads all images and sets the default category to "All Categories".

Example 2:

Input: mockImageData, Category selected: "Nature"
Output: Only the 5 images with category "Nature" are displayed, category dropdown showing "Nature" selected, pagination showing page 1 of 1 (if only 5 images).
Explanation: The gallery filters the images based on the selected category.

Example 3:

Input: mockImageData, Current Page: 2
Output: Images 11-20 are displayed, category dropdown showing the currently selected category, pagination showing page 2 of 2.
Explanation: The gallery displays the images for the specified page number.

Constraints

  • Images per Page: 10 images per page.
  • Data Source: Use the provided mockImageData for simulating API data. Do not make actual API calls.
  • Performance: The gallery should render efficiently, even with a large number of images (up to 20 in this case). Avoid unnecessary re-renders.
  • TypeScript: Strict TypeScript typing is expected.

Notes

  • Consider using React's useState hook for managing component state.
  • Think about how to efficiently filter the image data based on the selected category.
  • Pay attention to the UI updates when the state changes.
  • The mockImageData is provided below. You do not need to create this data.
  • Focus on creating a clean, well-structured, and maintainable React component.
interface ImageData {
  id: number;
  url: string;
  title: string;
  category: string;
}

const mockImageData: ImageData[] = [
  { id: 1, url: 'https://picsum.photos/id/10/200/300', title: 'Image 1', category: 'Nature' },
  { id: 2, url: 'https://picsum.photos/id/11/200/300', title: 'Image 2', category: 'City' },
  { id: 3, url: 'https://picsum.photos/id/12/200/300', title: 'Image 3', category: 'Nature' },
  { id: 4, url: 'https://picsum.photos/id/13/200/300', title: 'Image 4', category: 'Animals' },
  { id: 5, url: 'https://picsum.photos/id/14/200/300', title: 'Image 5', category: 'Nature' },
  { id: 6, url: 'https://picsum.photos/id/15/200/300', title: 'Image 6', category: 'City' },
  { id: 7, url: 'https://picsum.photos/id/16/200/300', title: 'Image 7', category: 'Animals' },
  { id: 8, url: 'https://picsum.photos/id/17/200/300', title: 'Image 8', category: 'Nature' },
  { id: 9, url: 'https://picsum.photos/id/18/200/300', title: 'Image 9', category: 'City' },
  { id: 10, url: 'https://picsum.photos/id/19/200/300', title: 'Image 10', category: 'Animals' },
  { id: 11, url: 'https://picsum.photos/id/20/200/300', title: 'Image 11', category: 'Nature' },
  { id: 12, url: 'https://picsum.photos/id/21/200/300', title: 'Image 12', category: 'City' },
  { id: 13, url: 'https://picsum.photos/id/22/200/300', title: 'Image 13', category: 'Animals' },
  { id: 14, url: 'https://picsum.photos/id/23/200/300', title: 'Image 14', category: 'Nature' },
  { id: 15, url: 'https://picsum.photos/id/24/200/300', title: 'Image 15', category: 'City' },
  { id: 16, url: 'https://picsum.photos/id/25/200/300', title: 'Image 16', category: 'Animals' },
  { id: 17, url: 'https://picsum.photos/id/26/200/300', title: 'Image 17', category: 'Nature' },
  { id: 18, url: 'https://picsum.photos/id/27/200/300', title: 'Image 18', category: 'City' },
  { id: 19, url: 'https://picsum.photos/id/28/200/300', title: 'Image 19', category: 'Animals' },
  { id: 20, url: 'https://picsum.photos/id/29/200/300', title: 'Image 20', category: 'Nature' },
];
Loading editor...
typescript