Hone logo
Hone
Problems

React useResizeObserver Hook

This challenge asks you to create a custom React hook, useResizeObserver, that leverages the ResizeObserver API to efficiently track changes in the size of a DOM element. This hook is useful for dynamically adjusting component layouts, triggering reflows, or performing calculations based on element dimensions, all while minimizing performance impact compared to polling for size changes.

Problem Description

You need to implement a useResizeObserver hook in TypeScript that takes a ref to a DOM element as input and returns an object containing the element's current width, height, and a boolean indicating whether the element has been resized. The hook should:

  1. Initialize a ResizeObserver: When the component mounts, create a ResizeObserver instance.
  2. Observe the Element: Attach the observer to the element referenced by the provided ref.
  3. Update State: When the element's size changes, update the hook's state with the new width and height.
  4. Cleanup: When the component unmounts, disconnect the ResizeObserver to prevent memory leaks.
  5. Handle Initial Size: Provide initial width and height values based on the element's size at mount time (if the element exists).
  6. Return Values: Return an object with the following properties:
    • width: The current width of the element in pixels.
    • height: The current height of the element in pixels.
    • isResized: A boolean indicating whether the element has been resized since the component mounted.

Key Requirements:

  • The hook must be written in TypeScript.
  • The hook must correctly handle the element's initial size.
  • The hook must disconnect the ResizeObserver on unmount.
  • The hook must efficiently update the component when the element's size changes.
  • The hook should handle cases where the ref is initially null or undefined.

Expected Behavior:

  • When the component mounts and the ref is valid, the hook should initialize the width and height with the element's current dimensions.
  • When the element is resized, the width and height values in the hook's state should be updated accordingly.
  • The isResized flag should be true after the first resize and remain true for subsequent resizes.
  • When the component unmounts, the ResizeObserver should be disconnected.
  • If the ref is initially null or undefined, the width and height should remain 0, and isResized should be false.

Examples

Example 1:

Input: A component with a ref attached to a div element that is initially 200px wide and 100px high.
Output: { width: 200, height: 100, isResized: false }
Explanation: The hook initializes the width and height with the element's initial dimensions and sets isResized to false.

Example 2:

Input: The same component as Example 1, but the div element is resized to 300px wide and 150px high.
Output: { width: 300, height: 150, isResized: true }
Explanation: The hook updates the width and height to reflect the new dimensions and sets isResized to true.

Example 3:

Input: A component with a ref that is initially null.
Output: { width: 0, height: 0, isResized: false }
Explanation: The hook initializes width and height to 0 and isResized to false because the ref is null.

Constraints

  • The hook must be compatible with React 16.8 or higher.
  • The hook should avoid unnecessary re-renders.
  • The hook should handle potential errors gracefully (e.g., if the element is removed from the DOM before the observer can be disconnected).
  • The hook should be performant and not introduce significant overhead.

Notes

  • Consider using useRef and useState hooks for managing the element ref and state.
  • The ResizeObserver API provides a callback function that is invoked when the element's size changes.
  • Remember to disconnect the ResizeObserver in the cleanup function to prevent memory leaks.
  • Think about how to handle the initial size of the element before the ResizeObserver callback is triggered.
  • The isResized flag is intended to indicate whether any resize has occurred since the component mounted, not just the most recent one.
Loading editor...
typescript