Skip to content

Comments

docs(react-native): fix example to include initial state#10172

Open
roitium wants to merge 1 commit intoTanStack:mainfrom
roitium:patch-1
Open

docs(react-native): fix example to include initial state#10172
roitium wants to merge 1 commit intoTanStack:mainfrom
roitium:patch-1

Conversation

@roitium
Copy link

@roitium roitium commented Feb 23, 2026

🎯 Changes

expo-network does not emit the current state immediately upon subscription. This causes onlineManager to default to "online" on cold starts, even if the device is actually offline. So we need to explicitly call Network.getNetworkStateAsync() to initialize the state correctly before setting up the listener.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Documentation
    • Enhanced React Native framework documentation with improved details on network state detection and connection initialization behavior.

@changeset-bot
Copy link

changeset-bot bot commented Feb 23, 2026

⚠️ No Changeset found

Latest commit: b97c8c0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added the documentation Improvements or additions to documentation label Feb 23, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

Updates React Native documentation to show initial asynchronous network state fetching using Expo Network API before event listener setup. Initializes online state from network state before subscribing to state change events. Only additions, no deletions or signature changes.

Changes

Cohort / File(s) Summary
Network State Initialization
docs/framework/react/react-native.md
Adds documentation of initial async network state fetch via Network.getNetworkStateAsync() to set online state before establishing event listener for continuous network state monitoring.

Poem

🐰 A network state fetched with care,
Async checks floating through the air,
Before the listener takes its place,
We prime the state with network grace!

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding initial state initialization to the React Native example.
Description check ✅ Passed The description includes all required template sections with clear problem explanation, solution details, and appropriate checklist responses. Marked as docs-only, which aligns with the changeset requirement.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/framework/react/react-native.md`:
- Around line 43-53: The async init in onlineManager.setEventListener can be
overwritten by a later listener event and lacks error handling: introduce a
local guard flag (e.g., "initialResultIgnored" or "stale") inside the
setEventListener callback that is flipped when the synchronous
addNetworkStateListener fires (or when its callback runs) so the Promise result
from Network.getNetworkStateAsync() only calls setOnline if the listener hasn't
already provided a newer state; also attach .catch(...) to
getNetworkStateAsync() to log/handle errors, and ensure you still return
eventSubscription.remove from the setEventListener callback (use the same
identifiers: Network.getNetworkStateAsync, Network.addNetworkStateListener,
setOnline, eventSubscription.remove).

Comment on lines 43 to 53
onlineManager.setEventListener((setOnline) => {
Network.getNetworkStateAsync().then((state) => {
setOnline(!!state.isConnected)
})

const eventSubscription = Network.addNetworkStateListener((state) => {
setOnline(!!state.isConnected)
})

return eventSubscription.remove
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Race condition: async fetch result can overwrite a more recent listener-fired state

Because getNetworkStateAsync() is asynchronous, the following sequence is possible:

  1. getNetworkStateAsync() is invoked — captures state at T₀ (e.g., offline).
  2. addNetworkStateListener is registered synchronously.
  3. A state change fires the listener at T₁setOnline(true).
  4. The async call resolves at T₂ with the stale T₀ snapshot → setOnline(false), silently overwriting the correct current state.

A guard flag prevents the async snapshot from clobbering a fresher listener result:

🐛 Proposed fix with race-safe initialization guard + error handling
 onlineManager.setEventListener((setOnline) => {
-  Network.getNetworkStateAsync().then((state) => {
-    setOnline(!!state.isConnected)
-  })
-
-  const eventSubscription = Network.addNetworkStateListener((state) => {
+  let initialised = false
+
+  const eventSubscription = Network.addNetworkStateListener((state) => {
+    initialised = true
     setOnline(!!state.isConnected)
   })
-  
+
+  Network.getNetworkStateAsync()
+    .then((state) => {
+      if (!initialised) {
+        setOnline(!!state.isConnected)
+      }
+    })
+    .catch(() => {
+      // getNetworkStateAsync can reject on some platforms/SDK versions
+    })
+
   return eventSubscription.remove
 })

Additionally, the bare .then() with no .catch() means that if getNetworkStateAsync() rejects (e.g., the native module is unavailable, which surfaces as an unhandled promise rejection), the error is silently swallowed and will appear as an unhandled rejection in the app. The .catch() in the proposed fix addresses both concerns.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onlineManager.setEventListener((setOnline) => {
Network.getNetworkStateAsync().then((state) => {
setOnline(!!state.isConnected)
})
const eventSubscription = Network.addNetworkStateListener((state) => {
setOnline(!!state.isConnected)
})
return eventSubscription.remove
})
onlineManager.setEventListener((setOnline) => {
let initialised = false
const eventSubscription = Network.addNetworkStateListener((state) => {
initialised = true
setOnline(!!state.isConnected)
})
Network.getNetworkStateAsync()
.then((state) => {
if (!initialised) {
setOnline(!!state.isConnected)
}
})
.catch(() => {
// getNetworkStateAsync can reject on some platforms/SDK versions
})
return eventSubscription.remove
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/framework/react/react-native.md` around lines 43 - 53, The async init in
onlineManager.setEventListener can be overwritten by a later listener event and
lacks error handling: introduce a local guard flag (e.g., "initialResultIgnored"
or "stale") inside the setEventListener callback that is flipped when the
synchronous addNetworkStateListener fires (or when its callback runs) so the
Promise result from Network.getNetworkStateAsync() only calls setOnline if the
listener hasn't already provided a newer state; also attach .catch(...) to
getNetworkStateAsync() to log/handle errors, and ensure you still return
eventSubscription.remove from the setEventListener callback (use the same
identifiers: Network.getNetworkStateAsync, Network.addNetworkStateListener,
setOnline, eventSubscription.remove).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant