mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
feat: 🎸 use only one useState and one useEffect call
This commit is contained in:
parent
5d31cf0dbc
commit
2d0fabf9ac
@ -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<UseBatteryState>({ isSupported: true, fetched: false });
|
||||
const battery = React.useRef<BatteryManager | null>();
|
||||
const isMounted = React.useRef(false);
|
||||
const [state, setState] = useState<UseBatteryState>({ isSupported: true, fetched: false });
|
||||
|
||||
const handleChange = React.useCallback(() => {
|
||||
if (!isMounted.current || !battery.current) {
|
||||
return;
|
||||
}
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
let battery: BatteryManager | null = null;
|
||||
|
||||
const newState: UseBatteryState = {
|
||||
isSupported: true,
|
||||
fetched: true,
|
||||
level: battery.current.level,
|
||||
charging: battery.current.charging,
|
||||
dischargingTime: battery.current.dischargingTime,
|
||||
chargingTime: battery.current.chargingTime,
|
||||
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);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user