diff --git a/src/useBattery.ts b/src/useBattery.ts index c2f6834fd0..3f675665b3 100644 --- a/src/useBattery.ts +++ b/src/useBattery.ts @@ -2,6 +2,8 @@ import * as React from 'react'; import * as isEqual from 'react-fast-compare'; import { off, on } from './util'; +const { useState, useEffect } = React; + export interface BatteryState { charging: boolean; chargingTime: number; @@ -33,68 +35,47 @@ function useBatteryMock(): UseBatteryState { } function useBattery(): UseBatteryState { - const [state, setState] = React.useState({ isSupported: true, fetched: false }); - const battery = React.useRef(); - const isMounted = React.useRef(false); - - const handleChange = React.useCallback(() => { - if (!isMounted.current || !battery.current) { - return; - } - - const newState: UseBatteryState = { - isSupported: true, - fetched: true, - level: battery.current.level, - charging: battery.current.charging, - dischargingTime: battery.current.dischargingTime, - chargingTime: battery.current.chargingTime, + const [state, setState] = useState({ isSupported: true, fetched: false }); + + useEffect(() => { + let isMounted = true; + let battery: BatteryManager | null = null; + + const handleChange = () => { + if (!isMounted || !battery) { + return; + } + const newState: UseBatteryState = { + isSupported: true, + fetched: true, + level: battery.level, + charging: battery.charging, + dischargingTime: battery.dischargingTime, + chargingTime: battery.chargingTime, + }; + !isEqual(state, newState) && setState(newState); }; - !isEqual(state, newState) && setState(newState); - }, [state, setState]); - - const bindBatteryEvents = React.useCallback(() => { - if (!battery.current || !isMounted.current) { - return; - } - - on(battery.current, 'chargingchange', handleChange); - on(battery.current, 'chargingtimechange', handleChange); - on(battery.current, 'dischargingtimechange', handleChange); - on(battery.current, 'levelchange', handleChange); - }, [handleChange]); - const unbindBatteryEvents = React.useCallback(() => { - if (!battery.current) { - return; - } - - off(battery.current, 'chargingchange', handleChange); - off(battery.current, 'chargingtimechange', handleChange); - off(battery.current, 'dischargingtimechange', handleChange); - off(battery.current, 'levelchange', handleChange); - }, [handleChange]); - - React.useEffect(() => { - bindBatteryEvents(); - handleChange(); // this one is for case when update performed between unbind and bind, extremely rare, but better to handle - - return unbindBatteryEvents; - }, [handleChange]); - - React.useEffect(() => { - isMounted.current = true; - (navigator as NavigatorWithPossibleBattery).getBattery!().then((bat: BatteryManager) => { - battery.current = bat; - - bindBatteryEvents(); + if (!isMounted) { + return; + } + battery = bat; + on(battery, 'chargingchange', handleChange); + on(battery, 'chargingtimechange', handleChange); + on(battery, 'dischargingtimechange', handleChange); + on(battery, 'levelchange', handleChange); handleChange(); }); return () => { - isMounted.current = false; - unbindBatteryEvents(); + isMounted = false; + if (battery) { + off(battery, 'chargingchange', handleChange); + off(battery, 'chargingtimechange', handleChange); + off(battery, 'dischargingtimechange', handleChange); + off(battery, 'levelchange', handleChange); + } }; }, []);