Hone logo
Hone
Problems

React Virtualized List Component

Creating a virtualized list component is crucial for efficiently rendering large datasets in React applications. Traditional rendering can lead to performance bottlenecks when dealing with thousands or millions of items, as all items are rendered and kept in the DOM. This challenge asks you to build a basic virtualized list that only renders items within the visible viewport, significantly improving performance.

Problem Description

You are tasked with building a simple virtualized list component in React using TypeScript. The component should accept an array of data items and render them as a list. The key requirement is that only a subset of the items, those currently visible within the viewport, should be rendered to the DOM. As the user scrolls, the component should dynamically update the rendered items to reflect the visible portion of the data.

Key Requirements:

  • Data Input: The component should accept a data prop, which is an array of any type T.
  • Item Rendering: The component should accept an itemRenderer prop, a function that takes a single item of type T and returns a React element to render for that item.
  • Viewport Calculation: The component should calculate the start and end indices of the items that are currently visible within the viewport.
  • Dynamic Rendering: Only the items within the calculated viewport indices should be rendered to the DOM.
  • Scrolling: The component should handle scrolling events and update the viewport calculation and rendered items accordingly.
  • List Size: The component should display the total number of items in the data array.

Expected Behavior:

  • When the component mounts, it should render the initial set of items visible in the viewport (assuming a default viewport height).
  • As the user scrolls, the component should dynamically update the rendered items to match the visible portion of the data.
  • The itemRenderer function should be called for each rendered item, allowing for custom rendering logic.
  • The component should handle cases where the data array is empty.
  • The component should handle cases where the viewport is smaller than the total number of items.

Edge Cases to Consider:

  • Empty data array.
  • Viewport height is zero or negative.
  • Data array contains items of varying heights (though this challenge focuses on uniform height for simplicity).
  • Scrolling beyond the bounds of the data array (though this is not a primary requirement, consider how it might be handled).

Examples

Example 1:

Input: data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], itemRenderer = (item) => <div>{item}</div>, viewportHeight = 200
Output: A list displaying items 1, 2, 3, 4, 5 (assuming each item takes up 20px of height, and the viewport can fit 10 items).  Scrolling down should render items 6, 7, 8.
Explanation: The component calculates the visible items based on the viewport height and renders only those.

Example 2:

Input: data = [], itemRenderer = (item) => <div>{item}</div>, viewportHeight = 200
Output: An empty list.
Explanation: The component handles the case where the data array is empty.

Example 3:

Input: data = [1, 2], itemRenderer = (item) => <div>{item}</div>, viewportHeight = 500
Output: A list displaying items 1 and 2.
Explanation: The component renders all items since the viewport is larger than the data array.

Constraints

  • Performance: The component should be performant, minimizing unnecessary re-renders. Avoid re-rendering items that are not visible.
  • Data Size: The data array can contain up to 1000 items.
  • Item Height: For simplicity, assume all items have a uniform height of 30px. This can be adjusted via a prop in a future iteration.
  • Viewport Height: The viewportHeight prop should be a positive number representing the height of the visible area in pixels.
  • TypeScript: The solution must be written in TypeScript.

Notes

  • Consider using React's useRef hook to manage the scroll position.
  • The itemRenderer function provides flexibility in how each item is rendered.
  • Focus on the core virtualization logic – you don't need to implement complex features like drag-and-drop or sorting.
  • Think about how to efficiently calculate the visible item indices based on the scroll position and item height.
  • A simple approach is to use a useEffect hook to listen for scroll events and update the rendered items accordingly. However, be mindful of performance implications within the useEffect.
Loading editor...
typescript