Skip to content

Commit 4c5271b

Browse files
sumchatteringclaude
andcommitted
fix: make @react-navigation/native an optional peer dependency (#770)
The SDK imported `useIsFocused` directly from `@react-navigation/native` in the IterableInbox component, causing build failures for apps that do not use React Navigation. This change introduces a wrapper hook that tries to load `useIsFocused` from `@react-navigation/native` at module load time and falls back to always returning `true` when the package is not installed. The peer dependency is also marked as optional in peerDependenciesMeta. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e69c305 commit 4c5271b

4 files changed

Lines changed: 54 additions & 2 deletions

File tree

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@
118118
"react-native-webview": "*"
119119
},
120120
"peerDependenciesMeta": {
121+
"@react-navigation/native": {
122+
"optional": true
123+
},
121124
"expo": {
122125
"optional": true
123126
}

src/core/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './useAppStateListener';
22
export * from './useDeviceOrientation';
3+
export * from './useIsFocused';

src/core/hooks/useIsFocused.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* The type of the `useIsFocused` hook from `@react-navigation/native`.
3+
*/
4+
type UseIsFocusedHook = () => boolean;
5+
6+
let _useIsFocused: UseIsFocusedHook | undefined;
7+
8+
/**
9+
* Attempts to load `useIsFocused` from `@react-navigation/native`.
10+
*
11+
* This is done once at module load time. If the package is not installed,
12+
* the import will fail and `_useIsFocused` will remain `undefined`.
13+
*/
14+
try {
15+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
16+
_useIsFocused = require('@react-navigation/native').useIsFocused;
17+
} catch {
18+
// @react-navigation/native is not installed; this is fine.
19+
}
20+
21+
/**
22+
* A fallback hook that always returns `true`.
23+
*
24+
* Used when `@react-navigation/native` is not installed. Since there is no
25+
* navigation container managing focus, the component is always considered
26+
* focused.
27+
*
28+
* @returns `true`
29+
*/
30+
function useAlwaysFocused(): boolean {
31+
return true;
32+
}
33+
34+
/**
35+
* A hook that returns whether the screen is currently focused.
36+
*
37+
* If `@react-navigation/native` is installed, this delegates to its
38+
* `useIsFocused` hook. Otherwise, it falls back to always returning `true`,
39+
* which is appropriate when no navigation container is in use (the component
40+
* is always "focused" if there is no navigation stack managing focus).
41+
*
42+
* @returns `true` if the screen is focused (or if React Navigation is not
43+
* installed), `false` otherwise.
44+
*/
45+
export const useIsFocused: UseIsFocusedHook = _useIsFocused ?? useAlwaysFocused;

src/inbox/components/IterableInbox.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { useIsFocused } from '@react-navigation/native';
21
import { useEffect, useState } from 'react';
32
import {
43
Animated,
@@ -11,7 +10,11 @@ import {
1110
import { SafeAreaView } from 'react-native-safe-area-context';
1211

1312
import RNIterableAPI from '../../api';
14-
import { useAppStateListener, useDeviceOrientation } from '../../core';
13+
import {
14+
useAppStateListener,
15+
useDeviceOrientation,
16+
useIsFocused,
17+
} from '../../core';
1518
// expo throws an error if this is not imported directly due to circular
1619
// dependencies
1720
// See: https://github.com/expo/expo/issues/35100

0 commit comments

Comments
 (0)