Skip to content

Commit 11be20c

Browse files
fix(useBattery): handle unmount cleanup and promise rejection
- Add mounted flag to prevent state updates after unmount - Prevent event listener registration if component unmounts before getBattery() resolves - Add .catch() handler to gracefully handle promise rejections - Fix misleading comment for fetched field
1 parent 243087f commit 11be20c

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

src/useBattery/index.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export type UseBatteryState = BatteryState & {
2727
*/
2828
isSupported: boolean;
2929
/**
30-
* Whether the battery state is currently being fetched.
30+
* Whether the battery state has been fetched.
3131
*/
3232
fetched: boolean;
3333
};
@@ -96,25 +96,43 @@ export function useBattery(): UseBatteryState {
9696
}
9797

9898
let battery: BatteryManager | null = null;
99+
let mounted = true;
99100

100101
const handleChange = () => {
101-
if (battery) {
102+
if (battery && mounted) {
102103
setState(getBatteryState(battery));
103104
}
104105
};
105106

106-
// eslint-disable-next-line @typescript-eslint/no-floating-promises,promise/catch-or-return,promise/prefer-await-to-then,promise/always-return
107-
nav.getBattery().then((b) => {
108-
battery = b;
109-
setState(getBatteryState(battery));
107+
// eslint-disable-next-line @typescript-eslint/no-floating-promises,promise/prefer-await-to-then,promise/always-return
108+
nav
109+
.getBattery()
110+
.then((b) => {
111+
if (!mounted) {
112+
return;
113+
}
114+
115+
battery = b;
116+
setState(getBatteryState(battery));
110117

111-
on(battery, 'chargingchange', handleChange);
112-
on(battery, 'chargingtimechange', handleChange);
113-
on(battery, 'dischargingtimechange', handleChange);
114-
on(battery, 'levelchange', handleChange);
115-
});
118+
on(battery, 'chargingchange', handleChange);
119+
on(battery, 'chargingtimechange', handleChange);
120+
on(battery, 'dischargingtimechange', handleChange);
121+
on(battery, 'levelchange', handleChange);
122+
})
123+
.catch((error) => {
124+
// Gracefully handle getBattery() rejections to avoid unhandled promise rejections
125+
if (process.env.NODE_ENV !== 'production') {
126+
// eslint-disable-next-line no-console
127+
console.error('Failed to get battery status:', error);
128+
}
129+
if (mounted) {
130+
setState(getBatteryState(null));
131+
}
132+
});
116133

117134
return () => {
135+
mounted = false;
118136
if (battery) {
119137
off(battery, 'chargingchange', handleChange);
120138
off(battery, 'chargingtimechange', handleChange);

0 commit comments

Comments
 (0)