Skip to content

Network

@symbiote-native/network wraps expo-network so every SymbioteNative adapter can read the device’s network connection state. Like battery, it’s built on expo-modules-core and mixes stateless one-shot calls with exactly one live subscription: useNetworkState/NetworkStateService.connect() seed from a one-shot getNetworkStateAsync() call and then subscribe to addNetworkStateListener for live updates, the same seed-then-subscribe shape as battery’s own hooks — everything else (getIpAddressAsync, isAirplaneModeEnabledAsync) is a plain stateless function, same as local-auth.

OS platform Support
iOS ✅ live
Android ✅ live
Framework adapter Support
React ✅ live
Vue ✅ live
Angular ✅ live
Svelte ✅ live
Terminal window
npm install @symbiote-native/network

expo-network and expo-modules-core come along as regular dependencies, pinned to exact versions — never install either yourself, and never add the expo meta-package to your project (it bundles its own Metro/Babel pipeline, which conflicts with this project’s own).

import { Text } from '@symbiote-native/react';
import { useNetworkState } from '@symbiote-native/network/react';
export default function ConnectionStatus() {
const networkState = useNetworkState(); // NetworkState, {} until the first reading arrives
return <Text>{networkState.isConnected ? `Connected via ${networkState.type}` : 'Offline'}</Text>;
}

The stateless functions are already framework-agnostic — import them straight from the package root, on any adapter:

import { getIpAddressAsync, isAirplaneModeEnabledAsync } from '@symbiote-native/network';
const ipAddress = await getIpAddressAsync(); // "0.0.0.0" if it could not be retrieved
const airplaneMode = await isAirplaneModeEnabledAsync();
Signature Description
getNetworkStateAsync(): Promise<NetworkState> Gets the device’s current network connection state — { type, isConnected, isInternetReachable }
getIpAddressAsync(): Promise<string> Gets the device’s current IPv4 address. Resolves "0.0.0.0" if it could not be retrieved
isAirplaneModeEnabledAsync(): Promise<boolean> Tells if the device is in airplane mode
addNetworkStateListener(listener): EventSubscription Subscribes to network-state-change events (connection type, connected, internet reachable); call .remove() on the returned subscription to unsubscribe. The primitive useNetworkState/NetworkStateService.connect() wrap

useNetworkState() / NetworkStateService.connect()

Section titled “useNetworkState() / NetworkStateService.connect()”
React (/react) Vue (/vue) Angular (/angular) Svelte (/svelte) Signature Returns
useNetworkState useNetworkState NetworkStateService.connect() useNetworkState () Live NetworkState — plain value (React), Ref<NetworkState> (Vue), Signal<NetworkState> (Angular), { readonly current: NetworkState } (Svelte, read as .current), seeded {}
Field Type Description
type NetworkStateType | undefined The current network connection type
isConnected boolean | undefined Whether there is an active network connection — does not mean internet is reachable. false when type is NONE/UNKNOWN, true otherwise
isInternetReachable boolean | undefined Whether the internet is reachable over the current connection — see the caveat above for the Android-vs-iOS check difference

NetworkStateEvent is a plain alias of NetworkState, passed as the argument to addNetworkStateListener’s listener.

Member Value Description
NONE 'NONE' No active network connection detected
UNKNOWN 'UNKNOWN' The connection type could not be determined
CELLULAR 'CELLULAR' Active connection over mobile data
WIFI 'WIFI' Active connection over Wi-Fi
BLUETOOTH 'BLUETOOTH' Active connection over Bluetooth. @platform android
ETHERNET 'ETHERNET' Active connection over Ethernet
WIMAX 'WIMAX' Active connection over WiMAX. @platform android
VPN 'VPN' Active connection over VPN. @platform android
OTHER 'OTHER' Active connection over any other type. @platform android
  • isAirplaneModeEnabledAsync throws on iOS rather than resolving false. iOS’s native module defines only getIpAddressAsync and getNetworkStateAsync, so the presence check in the core raises an UnavailabilityError before anything is called. Branch on Platform.OS === 'android' at a cross-platform call site.
  • getIpAddressAsync returns a Wi-Fi address on both platforms. iOS walks the interface list and keeps only interfaces named en*; Android reads WifiManager’s connection info. On a cellular-only connection both fall through to "0.0.0.0" — that value means “no Wi-Fi address”, not “the call failed”.
  • A one-shot getNetworkStateAsync() on iOS can block for up to five seconds and then look offline. The native module starts a throwaway NWPathMonitor for the call and waits on a semaphore; if no path update arrives in time it returns the same { type: 'NONE', isConnected: false, isInternetReachable: false } a genuinely disconnected device returns. The event path (addNetworkStateListener, and so useNetworkState) does not pay this cost — it reads the module’s own long-lived monitor.
  • Android state events are debounced by 250 ms. ConnectivityManager callbacks collapse onto a single delayed emission, so a burst of transitions arrives as one event and the settled state lands a quarter-second late. Disconnects are the exception — they are emitted immediately, to avoid re-reading a just-lost network as still connected.

@symbiote-native/network ships zero React/Vue/Angular logic in expo-network itself — that package’s own JS is hand-ported, verbatim, into this package’s own core/ (its types file has no expo meta-package import to swap out in the first place, unlike local-auth’s or brightness’s):

packages/network/src/
├── core/ getNetworkStateAsync/getIpAddressAsync/isAirplaneModeEnabledAsync +
│ addNetworkStateListener; native-module.ts resolves the single
│ `ExpoNetwork` native module via expo-modules-core's
│ requireNativeModule
├── react/hooks/use-network-state @symbiote-native/network/react
├── vue/composables/use-network-state @symbiote-native/network/vue
├── svelte/runes/use-network-state @symbiote-native/network/svelte
└── angular/services/network-state.service @symbiote-native/network/angular

Each adapter’s useNetworkState/NetworkStateService is a thin lifecycle wrapper — seed from the one-shot call, subscribe on mount, unsubscribe on unmount — over the same core functions, the same one-listener seed-then-subscribe shape as battery’s three hooks. The native code itself is never vendored or copied — expo-modules-autolinking resolves it straight out of node_modules (see the native setup guide).