useBattery

React hook to track the battery status of a user's device.

import { useState, useEffect } from 'react'

interface BatteryManager {
  level: number
  charging: boolean
  chargingTime: number
  dischargingTime: number
  addEventListener(
    type: string,
    listener: EventListener | EventListenerObject | null,
    options?: boolean | AddEventListenerOptions,
  ): void
  removeEventListener(
    type: string,
    listener: EventListener | EventListenerObject | null,
    options?: boolean | EventListenerOptions,
  ): void
}

interface BatteryState {
  supported: boolean
  loading: boolean
  level: number | null
  charging: boolean | null
  chargingTime: number | null
  dischargingTime: number | null
}

interface NavigatorWithBattery extends Navigator {
  getBattery: () => Promise<BatteryManager>
}

export const useBattery = () => {
  const [batteryState, setBatteryState] = useState<BatteryState>({
    supported: true,
    loading: true,
    level: null,
    charging: null,
    chargingTime: null,
    dischargingTime: null,
  })

  useEffect(() => {
    const _navigator = navigator as NavigatorWithBattery
    let battery: BatteryManager

    const handleBatteryChange = () => {
      setBatteryState({
        supported: true,
        loading: false,
        level: battery.level,
        charging: battery.charging,
        chargingTime: battery.chargingTime,
        dischargingTime: battery.dischargingTime,
      })
    }

    if (!_navigator.getBattery) {
      setBatteryState((batteryState) => ({
        ...batteryState,
        supported: false,
        loading: false,
      }))
      return
    }

    _navigator.getBattery().then((_battery) => {
      battery = _battery
      handleBatteryChange()

      _battery.addEventListener('levelchange', handleBatteryChange)
      _battery.addEventListener('chargingchange', handleBatteryChange)
      _battery.addEventListener('chargingtimechange', handleBatteryChange)
      _battery.addEventListener('dischargingtimechange', handleBatteryChange)
    })

    return () => {
      if (battery) {
        battery.removeEventListener('levelchange', handleBatteryChange)
        battery.removeEventListener('chargingchange', handleBatteryChange)
        battery.removeEventListener('chargingtimechange', handleBatteryChange)
        battery.removeEventListener(
          'dischargingtimechange',
          handleBatteryChange,
        )
      }
    }
  }, [])

  return batteryState
}

React 16.8 or higher

  • Name
    supported
    Type
    boolean
    Description

    Represents whether the Battery Status API is supported in the browser (true) or not (false).

  • Name
    loading
    Type
    boolean
    Description

    Represents if the battery information is loading (true) or not (false).

  • Name
    level
    Type
    number | null
    Description

    Represents the level of the battery. 0.0 means that the battery is discharged, and 1.0 means the battery is charged charged.

  • Name
    charging
    Type
    boolean | null
    Description

    Represents whether the battery is charging (true) or not (false).

  • Name
    chargingTime
    Type
    number | null
    Description

    Represents the time remaining in seconds until the battery is completely charged.

  • Name
    dischargingTime
    Type
    number | null
    Description

    Represents the time remaining in seconds until the battery is completely discharged.

import { useBattery } from './hooks/useBattery'

const App = () => {
  const { level, charging } = useBattery()

  return (
    <div>
      <p>Battery level:{level && level * 100}</p>
      <p>{charging ? 'Battery charging' : 'Battery not charging'}</p>
    </div>
  )
}

export default App

Here are some use cases where this React hook is useful:

  • Displaying the battery level in a user interface
  • Low battery level notifications