Skip to content

Commit ce01cba

Browse files
authored
fix: fallback to useEffect when no navigation library is available (#5)
1 parent 86cb6fa commit ce01cba

3 files changed

Lines changed: 47 additions & 17 deletions

File tree

src/react-native/focus-effect.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useEffect } from "react";
2+
3+
const getDefaultFocusEffectFactory = (): ((cb: () => void) => void) => {
4+
try {
5+
return require("expo-router").useFocusEffect;
6+
} catch {
7+
// Nothing we can do about it, it's not installed in the project.
8+
}
9+
10+
try {
11+
return require("@react-navigation/native").useFocusEffect;
12+
} catch {
13+
// Nothing we can do about it, it's not installed in the project.
14+
}
15+
16+
console.warn(
17+
"[react-native-grab] No supported router found — falling back to useEffect. This may cause issues. Provide a custom focus effect using the setFocusEffect function.",
18+
);
19+
20+
const useFallbackFocusEffect = (cb: () => void) => {
21+
useEffect(() => {
22+
return cb();
23+
}, [cb]);
24+
};
25+
26+
return useFallbackFocusEffect;
27+
};
28+
29+
let cachedFocusEffect: ((cb: () => void) => void) | null = null;
30+
31+
export const getFocusEffect = (): ((cb: () => void) => void) => {
32+
if (!cachedFocusEffect) {
33+
cachedFocusEffect = getDefaultFocusEffectFactory();
34+
}
35+
36+
return cachedFocusEffect;
37+
};
38+
39+
export const setFocusEffect = (impl: (cb: () => void) => void) => {
40+
cachedFocusEffect = impl;
41+
};

src/react-native/grab-screen.tsx

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,9 @@
11
import { useCallback, useRef } from "react";
22
import { View, type ViewProps } from "react-native";
33
import { setFocusedScreenRef } from "./containers";
4+
import { getFocusEffect } from "./focus-effect";
45

5-
const getFocusEffectImpl = (): ((cb: () => void) => void) => {
6-
try {
7-
return require("expo-router").useFocusEffect;
8-
} catch {
9-
// Nothing we can do about it, it's not installed in the project.
10-
}
11-
12-
try {
13-
return require("@react-navigation/native").useFocusEffect;
14-
} catch {
15-
// Nothing we can do about it, it's not installed in the project.
16-
}
17-
18-
throw new Error("No useFocusEffect implementation found");
19-
};
20-
21-
const useFocusEffect = getFocusEffectImpl();
6+
const useFocusEffect = getFocusEffect();
227

238
export type ReactNativeGrabScreenProps = ViewProps;
249

src/react-native/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,7 @@ export const ReactNativeGrabContextProvider: React.ComponentType<ReactNativeGrab
3030
export const enableGrabbing: () => void = __DEV__
3131
? require("./grab-controller").enableGrabbing
3232
: noop;
33+
34+
export const setFocusEffect: (impl: (cb: () => void) => void) => void = __DEV__
35+
? require("./focus-effect").setFocusEffect
36+
: noop;

0 commit comments

Comments
 (0)