[PR #8953] fix(expo): read cached session data from SecureStore on app startup #16568

Open
opened 2026-04-13 10:34:58 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8953
Author: @terijaki
Created: 4/4/2026
Status: 🔄 Open

Base: mainHead: fix/expo-session-cache-hydration


📝 Commits (3)

  • cfe4b0f fix(expo): read cached session data from SecureStore on app startup
  • 0140519 chore: add changeset
  • ed44cba fix(expo): treat missing/invalid expiresAt as expired in cache hydration

📊 Changes

3 files changed (+223 additions, -0 deletions)

View changed files

.changeset/fix-expo-session-cache-hydration.md (+5 -0)
📝 packages/expo/src/client.ts (+23 -0)
📝 packages/expo/test/expo.test.ts (+195 -0)

📄 Description

Closes #8952

Problem

The Expo client writes session data to SecureStore (${storagePrefix}_session_data) after every successful /get-session response, but never reads it back on startup. This causes the session atom to always initialize as { data: null, isPending: true }, resulting in a login screen flash for returning users until the /get-session network request completes.

Solution

Read the cached session data from SecureStore in getActions and hydrate the session atom with it as an optimistic value (stale-while-revalidate). The cached data is validated before use:

  • Must contain valid session.id and user.id
  • Must not be expired (checks session.expiresAt)
  • Respects disableCache option
  • Skipped on web (SecureStore is native-only)

The atom is set with isPending: true so the /get-session network request still runs and replaces the cached data with the fresh server response.

Tests

Added 4 test cases covering:

  • Hydration from valid cached session data
  • No hydration when cache is empty
  • No hydration when cached session is expired
  • No hydration when disableCache is true

Summary by cubic

Hydrates the Expo session on app startup by reading cached data from SecureStore, preventing the login screen flash for returning users. Uses the cache optimistically and replaces it with the next /get-session response.

  • Bug Fixes

    • Validate cache: require session.id and user.id; treat missing/invalid/expired session.expiresAt as expired.
    • Respect disableCache; skip on web.
    • Set isPending: true for stale-while-revalidate.
    • Tests for valid, empty, expired, invalid-expiresAt, and disabled-cache cases.
  • Dependencies

    • Add changeset to publish a patch for @better-auth/expo.

Written for commit ed44cbaf2f. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8953 **Author:** [@terijaki](https://github.com/terijaki) **Created:** 4/4/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/expo-session-cache-hydration` --- ### 📝 Commits (3) - [`cfe4b0f`](https://github.com/better-auth/better-auth/commit/cfe4b0f148bfd85e7d50e86cb9aefc6ac416c11c) fix(expo): read cached session data from SecureStore on app startup - [`0140519`](https://github.com/better-auth/better-auth/commit/0140519d4d4b48af6a4645b172fb3e76c55fe310) chore: add changeset - [`ed44cba`](https://github.com/better-auth/better-auth/commit/ed44cbaf2f7b3ac7d3efa01a8f1dc5728b7c7002) fix(expo): treat missing/invalid expiresAt as expired in cache hydration ### 📊 Changes **3 files changed** (+223 additions, -0 deletions) <details> <summary>View changed files</summary> ➕ `.changeset/fix-expo-session-cache-hydration.md` (+5 -0) 📝 `packages/expo/src/client.ts` (+23 -0) 📝 `packages/expo/test/expo.test.ts` (+195 -0) </details> ### 📄 Description Closes #8952 ## Problem The Expo client writes session data to SecureStore (`${storagePrefix}_session_data`) after every successful `/get-session` response, but never reads it back on startup. This causes the session atom to always initialize as `{ data: null, isPending: true }`, resulting in a login screen flash for returning users until the `/get-session` network request completes. ## Solution Read the cached session data from SecureStore in `getActions` and hydrate the session atom with it as an optimistic value (stale-while-revalidate). The cached data is validated before use: - Must contain valid `session.id` and `user.id` - Must not be expired (checks `session.expiresAt`) - Respects `disableCache` option - Skipped on web (SecureStore is native-only) The atom is set with `isPending: true` so the `/get-session` network request still runs and replaces the cached data with the fresh server response. ## Tests Added 4 test cases covering: - Hydration from valid cached session data - No hydration when cache is empty - No hydration when cached session is expired - No hydration when `disableCache` is `true` <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Hydrates the Expo session on app startup by reading cached data from `SecureStore`, preventing the login screen flash for returning users. Uses the cache optimistically and replaces it with the next `/get-session` response. - **Bug Fixes** - Validate cache: require `session.id` and `user.id`; treat missing/invalid/expired `session.expiresAt` as expired. - Respect `disableCache`; skip on web. - Set `isPending: true` for stale-while-revalidate. - Tests for valid, empty, expired, invalid-`expiresAt`, and disabled-cache cases. - **Dependencies** - Add changeset to publish a patch for `@better-auth/expo`. <sup>Written for commit ed44cbaf2f7b3ac7d3efa01a8f1dc5728b7c7002. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-13 10:34:58 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#16568