Skip to content

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

Merged
TkDodo merged 2 commits intoTanStack:mainfrom
roitium:patch-1
Feb 26, 2026
Merged

docs(react-native): fix example to include initial state#10172
TkDodo merged 2 commits intoTanStack:mainfrom
roitium:patch-1

Conversation

@roitium
Copy link
Contributor

@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
    • Updated React Native framework docs to describe faster, immediate network-state detection during setup so the app knows online/offline status promptly and reliably.

@changeset-bot
Copy link

changeset-bot bot commented Feb 23, 2026

⚠️ No Changeset found

Latest commit: 623ecaf

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b97c8c0 and 623ecaf.

📒 Files selected for processing (1)
  • docs/framework/react/react-native.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/framework/react/react-native.md

📝 Walkthrough

Walkthrough

Adds immediate initialization in onlineManager.setEventListener by calling Network.getNetworkStateAsync() to set the initial online state before subscribing to Network.addNetworkStateListener; uses an internal initialised flag and preserves existing listener and cleanup logic. No public/exported signatures changed. (50 words)

Changes

Cohort / File(s) Summary
Network State Initialization
docs/framework/react/react-native.md
Documents an added immediate initialization path: call Network.getNetworkStateAsync() to set online state before registering the existing Network.addNetworkStateListener. Notes an internal initialised flag and a no-op catch for rejected promise. No API/signature changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped in swift to check the air,
Async pinged the network there,
Before the listener learned to see,
I set the state — polite and free,
A tiny hop, a steady cheer!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing a React Native example to include initial network state initialization.
Description check ✅ Passed The description follows the required template with all sections completed: Changes section explains the problem and solution, Checklist is filled out, and Release Impact is addressed.
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).

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 26, 2026 14:10
@TkDodo TkDodo merged commit 3f30619 into TanStack:main Feb 26, 2026
4 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the React Native documentation to fix the expo-network example for managing online status. The change addresses the issue where expo-network's addNetworkStateListener does not emit the current state immediately upon subscription, which causes the onlineManager to incorrectly default to "online" on cold starts even when the device is offline.

Changes:

  • Added logic to explicitly fetch initial network state using Network.getNetworkStateAsync()
  • Implemented a race condition guard using an initialised flag to prevent duplicate state updates
  • Added error handling for platforms where getNetworkStateAsync() may reject

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
})
.catch(() => {
// getNetworkStateAsync can reject on some platforms/SDK versions
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

If getNetworkStateAsync() rejects (which the comment acknowledges can happen on some platforms/SDK versions) and the listener hasn't fired yet, the online state will never be initialized. The onlineManager will default to "online" (true), which could be incorrect if the device is actually offline. Consider adding logic in the catch block to handle this scenario, such as assuming offline as a safer default or attempting an alternative method to determine initial connectivity.

Suggested change
// getNetworkStateAsync can reject on some platforms/SDK versions
// getNetworkStateAsync can reject on some platforms/SDK versions
if (!initialised) {
// Fall back to a safer default when initial state is unknown
setOnline(false)
}

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +53
let initialised = false

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

Network.getNetworkStateAsync()
.then((state) => {
if (!initialised) {
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The variable name uses British spelling "initialised" while the codebase consistently uses American spelling "initialized" (see packages/angular-query-experimental/src/inject-is-fetching.ts:42, packages/react-query-next-experimental/src/HydrationStreamProvider.tsx:159). Consider changing to "initialized" for consistency with the rest of the codebase.

Suggested change
let initialised = false
const eventSubscription = Network.addNetworkStateListener((state) => {
initialised = true
setOnline(!!state.isConnected)
})
Network.getNetworkStateAsync()
.then((state) => {
if (!initialised) {
let initialized = false
const eventSubscription = Network.addNetworkStateListener((state) => {
initialized = true
setOnline(!!state.isConnected)
})
Network.getNetworkStateAsync()
.then((state) => {
if (!initialized) {

Copilot uses AI. Check for mistakes.
// getNetworkStateAsync can reject on some platforms/SDK versions
})

return eventSubscription.remove
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

Returning eventSubscription.remove directly may cause a this binding issue when the cleanup function is called. If remove is not bound to eventSubscription, calling it later will result in this being undefined. Consider wrapping it in an arrow function: return () => eventSubscription.remove() to ensure the correct context, similar to the pattern used in examples/react/react-native/src/hooks/useAppState.ts:9.

Suggested change
return eventSubscription.remove
return () => eventSubscription.remove()

Copilot uses AI. Check for mistakes.
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.

3 participants