Hone logo
Hone
Problems

React Image Gallery with Dynamic Loading

Build a responsive image gallery component in React using TypeScript. This gallery should efficiently load and display images, allowing users to browse through a collection. The challenge focuses on implementing core gallery features, including image display, selection, and a basic loading mechanism.

Problem Description

Your task is to create a React component that functions as an image gallery. This component will receive an array of image objects, each containing at least a url and an id. The gallery should display these images in a grid layout. Users should be able to click on an image to select it, visually indicating that it's active. For larger collections, implement a simple "load more" functionality to fetch additional images.

Key Requirements:

  1. Image Display: Render images from a given data source in a responsive grid.
  2. Image Selection: Allow users to click on an image to select it. The selected image should have a distinct visual style (e.g., a border, overlay). Only one image should be selectable at a time.
  3. Dynamic Loading: Implement a "Load More" button. When clicked, this button should fetch and display the next set of images.
  4. TypeScript: The entire solution must be written in TypeScript.

Expected Behavior:

  • Initially, a subset of images should be displayed.
  • Clicking an unselected image should select it and deselect any previously selected image.
  • Clicking a selected image should deselect it.
  • Clicking the "Load More" button should append more images to the gallery.

Edge Cases:

  • What happens if the initial data is empty?
  • What happens when there are no more images to load? The "Load More" button should be disabled or hidden.

Examples

Example 1: Initial Load

Input:

const images = [
  { id: 'img1', url: 'https://example.com/image1.jpg' },
  { id: 'img2', url: 'https://example.com/image2.jpg' },
  { id: 'img3', url: 'https://example.com/image3.jpg' },
  { id: 'img4', url: 'https://example.com/image4.jpg' },
  { id: 'img5', url: 'https://example.com/image5.jpg' },
];
const initialLoadCount = 3; // Assume this is passed as a prop or internal state

Output (Visual Representation):

A grid displaying image1.jpg, image2.jpg, image3.jpg. A "Load More" button is visible. No image is selected.

Explanation: The gallery initially loads initialLoadCount images.

Example 2: After Clicking "Load More" and Selecting an Image

Input (State after Example 1 and loading more):

// Internal state after loading more
const loadedImages = [
  { id: 'img1', url: 'https://example.com/image1.jpg' },
  { id: 'img2', url: 'https://example.com/image2.jpg' },
  { id: 'img3', url: 'https://example.com/image3.jpg' },
  { id: 'img4', url: 'https://example.com/image4.jpg' },
  { id: 'img5', url: 'https://example.com/image5.jpg' },
];
const selectedImageId = 'img2';

Output (Visual Representation):

A grid displaying image1.jpg, image2.jpg, image3.jpg, image4.jpg, image5.jpg. image2.jpg has a distinct selected style (e.g., a prominent border). The "Load More" button is visible (assuming more images are available).

Explanation: After clicking "Load More", the next set of images is displayed. image2 was then clicked and is now visually marked as selected.

Example 3: No More Images to Load

Input (State after loading all images):

const loadedImages = [
  { id: 'img1', url: 'https://example.com/image1.jpg' },
  { id: 'img2', url: 'https://example.com/image2.jpg' },
  { id: 'img3', url: 'https://example.com/image3.jpg' },
  { id: 'img4', url: 'https://example.com/image4.jpg' },
  { id: 'img5', url: 'https://example.com/image5.jpg' },
];
const selectedImageId = 'img4';
const allImagesLoaded = true; // Flag indicating no more images

Output (Visual Representation):

A grid displaying image1.jpg, image2.jpg, image3.jpg, image4.jpg, image5.jpg. image4.jpg has a distinct selected style. The "Load More" button is not visible or is disabled.

Explanation: All available images are displayed. Since allImagesLoaded is true, the "Load More" functionality is deactivated.

Constraints

  • The images prop will be an array of objects, where each object has at least an id (string) and a url (string).
  • The initialLoadCount prop will be a positive integer.
  • The number of images to load each time the "Load More" button is clicked will be consistent (e.g., always load 3 more images).
  • Assume the data fetching for "Load More" is simulated and doesn't require actual network requests for this challenge. You can manage the state of available images and loaded images internally.
  • The gallery should be reasonably responsive, adapting to different screen sizes.

Notes

  • Consider how you will manage the state for the currently displayed images and the selected image within your React component.
  • Think about how to simulate the "loading more" functionality. You might need to keep track of the index or count of already loaded images.
  • Styling for the selected image is up to your creativity, but it should be clearly distinguishable from unselected images.
  • For the grid layout, consider using CSS Grid or Flexbox.
  • You can define a type for your image objects for better TypeScript support.
Loading editor...
typescript