Hone logo
Hone
Problems

Implementing useReducedMotion Hook in React for Accessibility

The useReducedMotion hook is a valuable tool for improving the accessibility of React applications, particularly for users with vestibular disorders or those who prefer reduced motion. This hook detects the user's system preference for reduced motion (via prefers-reduced-motion media query) and provides a boolean value indicating whether animations should be disabled. This challenge asks you to implement this hook in TypeScript.

Problem Description

You are tasked with creating a custom React hook called useReducedMotion. This hook should:

  1. Detect System Preference: Utilize the prefers-reduced-motion media query to determine the user's system preference for reduced motion.
  2. Return a Boolean Value: Return a boolean value indicating whether reduced motion is preferred by the user. true signifies that reduced motion is preferred, and false signifies that animations are acceptable.
  3. React to Changes: The hook should re-render whenever the user's preference changes. This ensures that your application dynamically adapts to the user's settings.
  4. Handle Initial Load: The hook should provide a sensible initial value while the media query is being evaluated. A default of false (animations enabled) is acceptable.

Expected Behavior:

  • When the user's system preference is set to reduce, the hook should return true.
  • When the user's system preference is set to no-preference or any, the hook should return false.
  • The hook should re-render whenever the prefers-reduced-motion media query changes.

Edge Cases to Consider:

  • Initial Load: The media query might not be immediately available on initial load. The hook should handle this gracefully and provide a default value.
  • Browser Support: While prefers-reduced-motion is widely supported, consider that older browsers might not support it. The hook should still function without errors in such cases (returning false is a reasonable fallback).

Examples

Example 1:

Input: User's system preference is set to "reduce".
Output: true
Explanation: The hook detects the "reduce" preference and returns true, indicating that animations should be disabled.

Example 2:

Input: User's system preference is set to "no-preference".
Output: false
Explanation: The hook detects the "no-preference" preference and returns false, indicating that animations are acceptable.

Example 3:

Input: Initial load of the application before the media query is evaluated.
Output: false
Explanation: The hook returns a default value of false (animations enabled) until the media query is evaluated.

Constraints

  • Language: TypeScript
  • React Version: Compatible with React 18 or later.
  • Performance: The hook should be performant and avoid unnecessary re-renders. Use useLayoutEffect judiciously if needed, but prioritize useEffect for this scenario.
  • Dependencies: The solution should minimize external dependencies. Only use built-in React APIs.

Notes

  • You can use matchMedia from the window object to access the prefers-reduced-motion media query.
  • Consider using a functional component and the useState hook to manage the state of the preference.
  • Think about how to handle the initial load and the asynchronous nature of media query evaluation.
  • The goal is to create a reusable hook that can be easily integrated into any React component to control animations based on user preference.
Loading editor...
typescript