React Battery Status Hook
This challenge involves creating a custom React hook, useBattery, that leverages the Browser Battery Status API to provide real-time battery information to your React components. This hook is useful for applications that need to adapt their behavior based on battery level, such as optimizing performance or informing users about power status.
Problem Description
Your task is to implement a custom React hook named useBattery that returns the current battery status of the user's device.
Key Requirements:
- Hook Signature: The hook should be a function named
useBatterythat takes no arguments and returns an object containing battery information. - Battery Information: The returned object should include:
level: A number representing the battery charge level (from 0 to 1).charging: A boolean indicating whether the device is currently charging.discharging: A boolean indicating whether the device is currently discharging (i.e., not charging and battery level is decreasing). This can be inferred.isSupported: A boolean indicating whether the Battery Status API is supported by the browser.
- Real-time Updates: The hook must subscribe to battery level and charging status changes and update its returned state accordingly.
- Cleanup: The hook must properly unsubscribe from battery events when the component unmounts to prevent memory leaks.
- Initial State: The hook should attempt to get the initial battery status when it's first called.
Expected Behavior:
- When the hook is used, it should immediately fetch the current battery status.
- As the battery level or charging status changes, the state returned by the hook should update.
- If the Battery Status API is not available,
isSupportedshould befalse, and other properties might reflect a default or unavailable state.
Edge Cases:
- API Not Supported: The browser might not support the Battery Status API. The hook should gracefully handle this.
- No Battery: The device might not have a battery (e.g., a desktop computer). The API might return specific values or throw errors in such cases.
Examples
Example 1: Basic Usage
Assume a component uses the useBattery hook.
import React from 'react';
import useBattery from './useBattery'; // Assuming your hook is in this file
function BatteryDisplay() {
const { level, charging, isSupported } = useBattery();
if (!isSupported) {
return <p>Battery Status API not supported.</p>;
}
return (
<div>
<p>Battery Level: {Math.round(level * 100)}%</p>
<p>Status: {charging ? 'Charging' : 'Discharging'}</p>
</div>
);
}
Output (when battery is 75% and not charging):
<div>
<p>Battery Level: 75%</p>
<p>Status: Discharging</p>
</div>
Explanation: The useBattery hook correctly retrieves the current battery level (0.75) and charging status (false), making them available to the BatteryDisplay component.
Example 2: Charging State
import React from 'react';
import useBattery from './useBattery';
function BatteryStatusIndicator() {
const { level, charging } = useBattery();
return (
<div style={{ color: charging ? 'green' : 'red' }}>
{charging ? 'Charging...' : 'On Battery'} ({Math.round(level * 100)}%)
</div>
);
}
Output (when battery is 90% and charging):
<div style="color: green;">
Charging... (90%)
</div>
Explanation: The hook detects the charging state as true, and the component uses this information to change the text and color.
Example 3: API Not Supported
import React from 'react';
import useBattery from './useBattery';
function ConditionalComponent() {
const { isSupported } = useBattery();
return (
<div>
{isSupported ? (
<p>You can view battery information.</p>
) : (
<p>Battery information is not available on this device.</p>
)}
</div>
);
}
Output (in a browser without Battery Status API):
<div>
<p>Battery information is not available on this device.</p>
</div>
Explanation: The isSupported flag correctly identifies that the API is not available, and the component renders the appropriate message.
Constraints
- Browser API: The solution must rely on the standard
navigator.getBattery()API and its associated events. - React Version: Compatible with React 16.8+ (Hooks).
- TypeScript: The hook and any related types must be written in TypeScript.
- No External Libraries: Do not use any third-party libraries to implement the Battery Status API functionality.
Notes
- The
navigator.getBattery()method returns aPromisethat resolves to aBatteryManagerobject. - The
BatteryManagerobject has properties likelevelandcharging, and it dispatches events likelevelchangeandchargingchange. - Consider how to handle potential errors when calling
navigator.getBattery(). - The
dischargingstate can be derived fromchargingandlevel. Ifchargingisfalseandlevelis less than 1, the device is likely discharging. - Think about the initial state of your hook before the battery promise resolves.