mirror of
https://github.com/streamich/react-use.git
synced 2026-01-25 14:17:16 +00:00
parent
b93bb0a6ed
commit
310fb6dc55
@ -2,6 +2,9 @@
|
||||
|
||||
React sensor hook that tracks battery status.
|
||||
|
||||
>**Note:** current `BatteryManager` API state is obsolete.
|
||||
>Although it may still work in some browsers, its use is discouraged since it could be removed at any time.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
@ -9,12 +12,34 @@ React sensor hook that tracks battery status.
|
||||
import {useBattery} from 'react-use';
|
||||
|
||||
const Demo = () => {
|
||||
const state = useBattery();
|
||||
const batteryState = useBattery();
|
||||
|
||||
if (!batteryState.isSupported) {
|
||||
return (
|
||||
<div>
|
||||
<strong>Battery sensor</strong>: <pre>not supported</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<pre>
|
||||
{JSON.stringify(state, null, 2)}
|
||||
</pre>
|
||||
<div>
|
||||
<strong>Battery sensor</strong>: <span>supported</span><br />
|
||||
<strong>Charge level</strong>: <span>{(batteryState.level * 100).toFixed(0)}%</span><br />
|
||||
<strong>Charging</strong>: <span>{batteryState.charging ? 'yes' : 'no'}</span><br />
|
||||
<strong>Charging time</strong>: <span>{batteryState.chargingTime ? batteryState.chargingTime : 'finished'}</span><br />
|
||||
<strong>Discharging time</strong>: <span>{batteryState.dischargingTime}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
const {isSupported, level, charging, dischargingTime, chargingTime} = useBattery();
|
||||
```
|
||||
- **`isSupported`**_`: boolean`_ - wheter browser/devise supports BatteryManager;
|
||||
- **`level`**_`: number`_ - representing the system's battery charge level scaled to a value between 0.0 and 1.0.
|
||||
- **`charging`**_`: boolean`_ - indicating whether or not the battery is currently being charged.
|
||||
- **`dischargingTime`**_`: number`_ - remaining time in seconds until the battery is completely discharged and the system will suspend.
|
||||
- **`chargingTime`**_`: number`_ - remaining time in seconds until the battery is fully charged, or 0 if the battery is already fully charged.
|
||||
|
||||
@ -4,9 +4,29 @@ import { useBattery } from '..';
|
||||
import ShowDocs from './util/ShowDocs';
|
||||
|
||||
const Demo = () => {
|
||||
const state = useBattery();
|
||||
const batteryState = useBattery();
|
||||
|
||||
return <pre>{JSON.stringify(state, null, 2)}</pre>;
|
||||
if (!batteryState.isSupported) {
|
||||
return (
|
||||
<div>
|
||||
<strong>Battery sensor</strong>: <pre>not supported</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<strong>Battery sensor</strong>: <span>supported</span>
|
||||
<br />
|
||||
<strong>Charge level</strong>: <span>{(batteryState.level * 100).toFixed(0)}%</span>
|
||||
<br />
|
||||
<strong>Charging</strong>: <span>{batteryState.charging ? 'yes' : 'no'}</span>
|
||||
<br />
|
||||
<strong>Charging time</strong>:
|
||||
<span>{batteryState.chargingTime ? batteryState.chargingTime : 'finished'}</span>
|
||||
<br />
|
||||
<strong>Discharging time</strong>: <span>{batteryState.dischargingTime}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('Sensors|useBattery', module)
|
||||
|
||||
@ -1,56 +1,106 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import * as React from 'react';
|
||||
import { off, on } from './util';
|
||||
|
||||
export interface BatterySensorState {
|
||||
charging: boolean;
|
||||
level: number;
|
||||
chargingTime: number;
|
||||
dischargingTime: number;
|
||||
enum BatteryManagerEvents {
|
||||
levelChange = 'levelchange',
|
||||
dischargingTimeChange = 'dischargingtimechange',
|
||||
chargingTimeChange = 'chargingtimechange',
|
||||
chargingChange = 'chargingchange',
|
||||
}
|
||||
|
||||
const useBattery = () => {
|
||||
const [state, setState] = useState({});
|
||||
let mounted = true;
|
||||
let battery: any = null;
|
||||
export interface BatteryState {
|
||||
charging: boolean;
|
||||
chargingTime: number;
|
||||
dischargingTime: number;
|
||||
level: number;
|
||||
}
|
||||
|
||||
const onChange = () => {
|
||||
const { charging, level, chargingTime, dischargingTime } = battery;
|
||||
setState({
|
||||
charging,
|
||||
level,
|
||||
chargingTime,
|
||||
dischargingTime,
|
||||
});
|
||||
};
|
||||
interface BatteryManager extends Readonly<BatteryState>, EventTarget {
|
||||
onchargingchange: () => void;
|
||||
onchargingtimechange: () => void;
|
||||
ondischargingtimechange: () => void;
|
||||
onlevelchange: () => void;
|
||||
}
|
||||
|
||||
const onBattery = () => {
|
||||
onChange();
|
||||
on(battery, 'chargingchange', onChange);
|
||||
on(battery, 'levelchange', onChange);
|
||||
on(battery, 'chargingtimechange', onChange);
|
||||
on(battery, 'dischargingtimechange', onChange);
|
||||
};
|
||||
interface NavigatorWithPossibleBattery extends Navigator {
|
||||
getBattery?: () => Promise<BatteryManager>;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
(navigator as any).getBattery().then((bat: any) => {
|
||||
if (mounted) {
|
||||
battery = bat;
|
||||
onBattery();
|
||||
}
|
||||
});
|
||||
const nav: NavigatorWithPossibleBattery = navigator;
|
||||
|
||||
return () => {
|
||||
mounted = false;
|
||||
if (battery) {
|
||||
off(battery, 'chargingchange', onChange);
|
||||
off(battery, 'levelchange', onChange);
|
||||
off(battery, 'chargingtimechange', onChange);
|
||||
off(battery, 'dischargingtimechange', onChange);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return state;
|
||||
type UseBatteryState = BatteryState & {
|
||||
isSupported: boolean;
|
||||
};
|
||||
|
||||
export default useBattery;
|
||||
export default function useBattery() {
|
||||
const [state, setState] = React.useState<UseBatteryState>({
|
||||
isSupported: nav && typeof nav.getBattery !== 'undefined',
|
||||
level: 1,
|
||||
charging: true,
|
||||
dischargingTime: Infinity,
|
||||
chargingTime: 0,
|
||||
});
|
||||
const battery = React.useRef<BatteryManager>();
|
||||
let isMounted = true;
|
||||
|
||||
if (state.isSupported) {
|
||||
const onChange = React.useCallback(() => {
|
||||
if (isMounted && battery.current) {
|
||||
setState({
|
||||
isSupported: true,
|
||||
level: battery.current.level,
|
||||
charging: battery.current.charging,
|
||||
dischargingTime: battery.current.dischargingTime,
|
||||
chargingTime: battery.current.chargingTime,
|
||||
});
|
||||
}
|
||||
}, [setState]);
|
||||
|
||||
const bindBatteryEvents = React.useCallback(
|
||||
(bat: BatteryManager) => {
|
||||
on(bat, BatteryManagerEvents.chargingChange, onChange);
|
||||
on(bat, BatteryManagerEvents.chargingTimeChange, onChange);
|
||||
on(bat, BatteryManagerEvents.dischargingTimeChange, onChange);
|
||||
on(bat, BatteryManagerEvents.levelChange, onChange);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const unbindBatteryEvents = React.useCallback(
|
||||
(bat: BatteryManager) => {
|
||||
off(bat, BatteryManagerEvents.chargingChange, onChange);
|
||||
off(bat, BatteryManagerEvents.chargingTimeChange, onChange);
|
||||
off(bat, BatteryManagerEvents.dischargingTimeChange, onChange);
|
||||
off(bat, BatteryManagerEvents.levelChange, onChange);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
battery.current && bindBatteryEvents(battery.current);
|
||||
|
||||
return () => {
|
||||
battery.current && unbindBatteryEvents(battery.current);
|
||||
};
|
||||
}, [onChange]);
|
||||
|
||||
React.useEffect(() => {
|
||||
nav.getBattery!().then((bat: BatteryManager) => {
|
||||
if (!isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
battery.current = bat;
|
||||
bindBatteryEvents(bat);
|
||||
});
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
|
||||
battery.current && unbindBatteryEvents(battery.current);
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user