This is test task, i made by custom requremenents.
Description:
The problem Create an infinite image carousel (the items loop when the either end is reached) using React. Navigation inside the carousel should only be triggered by scroll, rather than arrows or buttons.
Task:
Requirements The component must:
- Work with images of different sizes and aspect ratios
- Work on devices with different screen sizes
- Work on both mobile and desktop
- Work equally well with a dozen of images, as well as 1000+ images
- Be reusable
- You can use the Picsum list api or any other public api to get the images - https://picsum.photos/
Features
- Infinite Horizontal Scrolling: Automatically loads more images as the user scrolls.
- Responsive Design: Works seamlessly on both mobile and desktop.
- Optimized Performance: Supports 1000+ images with efficient pagination and lazy loading.
- Reusable Component: Easy to integrate into other projects as a standalone component.
- Tech Stack: Built with React, TypeScript, Redux Toolkit, and Styled Components.
The carousel uses the IntersectionObserver API for efficient infinite scrolling detection. This modern browser API provides better performance compared to scroll event listeners:
// src/hooks/useObserver.ts
const observer = new IntersectionObserver(
(entries) => {
const [entry] = entries;
if (entry.isIntersecting) {
dispatch(incrementPage());
}
},
{ threshold: 1.0 }
);The observer watches the last image element and triggers pagination when it becomes fully visible (threshold: 1.0), ensuring smooth infinite scrolling without performance bottlenecks.
The project implements a clean separation of concerns using custom hooks:
- Manages IntersectionObserver lifecycle
- Handles automatic pagination when last image becomes visible
- Prevents multiple API calls during loading states
- Handles image fetching logic
- Integrates with Redux Toolkit for state management
- Triggers API calls when page number changes
- Provides fallback scroll detection for older browsers
- Uses
useCallbackfor performance optimization - Implements scroll threshold logic for pagination
State management is handled with Redux Toolkit for predictable state updates:
// Async thunk for API calls
export const fetchImages = createAsyncThunk(
'images/fetchImages',
async (page: number) => {
const response = await fetch(`https://picsum.photos/v2/list?page=${page}&limit=10`);
const data = await response.json();
return data.map((item: any) => ({
id: item.id,
download_url: item.download_url,
}));
}
);The UI is built with Styled Components for maintainable CSS-in-JS:
- Responsive design with flexbox layouts
- Smooth scroll behavior with
scroll-behavior: smooth - Custom loading animations with keyframes
- Mobile-first responsive breakpoints
- Lazy Loading: Images load only when needed
- Pagination: 10 images per page to manage memory
- Memoized Callbacks: Prevents unnecessary re-renders
- IntersectionObserver: Efficient scroll detection
- Cleanup: Proper observer cleanup to prevent memory leaks
The project includes comprehensive testing with React Testing Library:
- Component rendering tests
- User interaction simulations
- Async operation testing
- Redux state management tests
- Clone the repository:
- Download repository (.zip) file
infinite_carousel.zip
- Usage
- Go to project root folder and run:
# install
npm install
#start
npm start-
Open
http://localhost:3000(or actual running server port) in your browser to view the application. -
Test
- Run command
npm test -- Carousel.test.tsxEnsure you have Node.js and npm installed:
-
Node.js (v16+)
-
npm (v7+)
- React 18.3.1: Latest React with concurrent features
- TypeScript 4.9.5: Type-safe development
- Redux Toolkit 2.3.0: Modern Redux with built-in best practices
- Styled Components 6.1.13: CSS-in-JS with theme support
- React Testing Library: Component testing utilities
- Jest: Test runner with DOM testing environment
- ESLint: Code quality and consistency
- Web Vitals: Performance monitoring
The IntersectionObserver API is supported in all modern browsers:
- Chrome 51+
- Firefox 55+
- Safari 12.1+
- Edge 15+
For older browsers, the useScrollHandler hook provides fallback functionality using traditional scroll event listeners.