Skip to content

Clerk Auth Implementation#4

Merged
saikumarbt merged 5 commits into
mainfrom
clerk-auth-implementation
Jul 3, 2026
Merged

Clerk Auth Implementation#4
saikumarbt merged 5 commits into
mainfrom
clerk-auth-implementation

Conversation

@saikumarbt

Copy link
Copy Markdown
Owner

No description provided.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@saikumarbt, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 14d9baac-128c-47f3-98ed-5d9ab44e6bff

📥 Commits

Reviewing files that changed from the base of the PR and between 7864dd4 and f1a5e5e.

📒 Files selected for processing (2)
  • app/(tabs)/index.tsx
  • app/_layout.tsx

Walkthrough

Integrates Clerk authentication into the Expo app with a root provider, auth-gated auth/tab layouts, sign-in and sign-up flows, authenticated user UI in tabs, and fallback text for missing subscription fields.

Changes

Clerk Authentication Integration

Layer / File(s) Summary
ClerkProvider wiring and dependencies
package.json, app.json, .env.example, app/_layout.tsx
Adds Clerk and secure storage dependencies and plugins, adds the Clerk publishable key env example, and wraps the root Stack in ClerkProvider with tokenCache and an env check.
Auth-gated layout guards
app/(auth)/_layout.tsx, app/(tabs)/_layout.tsx
Adds Clerk auth checks to the auth and tab layouts, returning null while loading and redirecting signed-in or signed-out users to the appropriate route.
Sign-in screen
app/(auth)/sign-in.tsx
Replaces the placeholder with a Clerk sign-in form that handles email/password entry, client-trust email-code verification, field errors, and completion navigation.
Sign-up screen
app/(auth)/sign-up.tsx
Replaces the placeholder with a Clerk sign-up form that creates an account, verifies email codes, handles completion, and renders the required captcha placeholder.
Authenticated user data in tabs
app/(tabs)/index.tsx, app/(tabs)/settings.tsx
Updates the home and settings screens to read Clerk user data, render avatars and profile fields, and expose sign-out actions.
SubscriptionCard fallback
components/SubscriptionCard.tsx
Adds "Not provided" as the fallback display value for missing subscription details.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Poem

A bunny hopped in, credential in paw,
Through Clerk’s little gate with a cheerful hurrah.
Codes in the mailbox, profiles in sight,
Tabs now know who’s signed in tonight.
If fields are missing, no fret, no distress—
“Not provided” keeps the fluffiness.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No description was provided, so there is no meaningful text to assess. Add a brief description of the Clerk authentication changes and affected screens or configuration.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the change set, which implements Clerk-based authentication.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch clerk-auth-implementation

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/_layout.tsx`:
- Around line 36-40: The ClerkProvider setup currently relies on a non-null
assertion for process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY, which can still
pass undefined at runtime and hide misconfiguration. Update the _layout
component to validate the Clerk publishable key before rendering ClerkProvider,
and throw a descriptive error if it is missing so the app fails fast during
bootstrap. Use the existing tokenCache and ClerkProvider render path as the
place to insert this guard, keeping the check close to where the key is
consumed.
- Around line 36-40: The root layout is hiding the splash too early, which can
reveal a blank frame before Clerk auth finishes loading. Update the root layout
in the component that wraps ClerkProvider and Stack to keep the
splash/placeholder visible until Clerk is loaded, or render a minimal loading
shell there instead of relying only on font readiness. Coordinate this with the
auth and tabs layouts that use useAuth().isLoaded so the app does not briefly
return null during cold start.

In `@app/`(auth)/sign-in.tsx:
- Around line 31-32: The sign-in flow is logging sensitive auth/session data in
`signIn` and related success/error paths, so replace the raw JSON/stringified
payloads and `session?.currentTask` output with generic messages only. Update
the logging in `app/(auth)/sign-in.tsx` around the `error` handling and session
usage to be gated behind `__DEV__`, and keep production logs free of auth
details.
- Around line 46-53: The sign-in flow in the needs_client_trust branch can
advance to the verification screen even when the email-code challenge is
unavailable or sendEmailCode() fails. Update the sign-in handler around
signIn.status, emailCodeFactor, and signIn.mfa.sendEmailCode() so the
verification step is reached only after confirming the email_code factor exists
and the challenge request succeeds; otherwise stop the transition and surface a
recoverable error or fallback path.

In `@app/`(auth)/sign-up.tsx:
- Around line 31-32: The sign-up error handling currently logs raw Clerk auth
state, which can expose sensitive identifiers and session details. In the
sign-up flow, update the `error` logging around the `signUp` /
`session.currentTask` checks to use a short dev-only message instead of
serializing the objects directly. Keep any debugging output gated behind a
development-only condition so nothing sensitive is emitted in production.
- Around line 99-102: The resend action in the sign-up flow is not guarded, so
repeated taps on the Pressable can trigger duplicate sendEmailCode() requests
and swallow failures. Update the signUp.verifications.sendEmailCode handler to
track an in-flight/loading state, disable the Pressable while the request is
pending, and catch errors so they surface as a local error state instead of
failing silently.
- Line 36: The sign-up flow in sign-up.tsx currently sends an email code
unconditionally after signUp.password(), which can stall when the remaining
missing_requirements are not an unverified email address. Update the logic
around signUp.password() and signUp.verifications.sendEmailCode() to first
inspect the Clerk state: if signUp.password() can already complete, finalize the
flow there, and only call sendEmailCode() when missing_requirements explicitly
includes an unverified email_address. Use the existing signUp,
missing_requirements, and sendEmailCode symbols to place the fix in the correct
branch.

In `@app/`(tabs)/index.tsx:
- Around line 21-22: The import order in index.tsx is invalid because the later
ESM imports must stay before the runtime statement that defines SafeAreaView.
Move the useUser/useClerk and Pressable imports above the SafeAreaView styled
declaration, keeping all imports grouped at the top so the module parses
correctly.

In `@app/`(tabs)/settings.tsx:
- Around line 13-15: The fallback display name and email lookup in settings are
using emailAddresses[0], which can pick the wrong address for users with
multiple emails. Update the settings screen logic around the displayName and
email values to use the primary email source instead of the first entry, and
apply the same fallback-name pattern used in app/(tabs)/index.tsx so both places
resolve identity from the same reliable field.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 853cc3d1-4400-4c86-b3b8-6eea82a75f4a

📥 Commits

Reviewing files that changed from the base of the PR and between 9f154ad and 152915b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • app.json
  • app/(auth)/_layout.tsx
  • app/(auth)/sign-in.tsx
  • app/(auth)/sign-up.tsx
  • app/(tabs)/_layout.tsx
  • app/(tabs)/index.tsx
  • app/(tabs)/settings.tsx
  • app/_layout.tsx
  • components/SubscriptionCard.tsx
  • package.json

Comment thread app/_layout.tsx
Comment thread app/(auth)/sign-in.tsx
Comment on lines +31 to +32
if (error) {
console.error(JSON.stringify(error, null, 2));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file list =="
git ls-files 'app/(auth)/sign-in.tsx'

echo
echo "== outline =="
ast-grep outline 'app/(auth)/sign-in.tsx' --view expanded || true

echo
echo "== relevant lines =="
cat -n 'app/(auth)/sign-in.tsx' | sed -n '1,220p'

echo
echo "== console usages in file =="
rg -n 'console\.(log|error)|__DEV__|session\?\.currentTask|JSON\.stringify\(error' 'app/(auth)/sign-in.tsx'

Repository: saikumarbt/react-native-recurly

Length of output: 8692


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Inspecting app/(auth)/sign-in.tsx...\n'
if [ -f 'app/(auth)/sign-in.tsx' ]; then
  nl -ba 'app/(auth)/sign-in.tsx' | sed -n '1,220p'
fi

Repository: saikumarbt/react-native-recurly

Length of output: 246


Avoid logging raw auth/session payloads. JSON.stringify(error, null, 2) and session?.currentTask can leak sensitive auth details into device logs; keep these messages generic and behind __DEV__. Also applies to app/(auth)/sign-in.tsx:39-40, 63-64.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(auth)/sign-in.tsx around lines 31 - 32, The sign-in flow is logging
sensitive auth/session data in `signIn` and related success/error paths, so
replace the raw JSON/stringified payloads and `session?.currentTask` output with
generic messages only. Update the logging in `app/(auth)/sign-in.tsx` around the
`error` handling and session usage to be gated behind `__DEV__`, and keep
production logs free of auth details.

Comment thread app/(auth)/sign-in.tsx
Comment on lines +46 to +53
} else if (signIn.status === "needs_client_trust") {
const emailCodeFactor = signIn.supportedSecondFactors.find(
(factor) => factor.strategy === "email_code",
);

if (emailCodeFactor) {
await signIn.mfa.sendEmailCode();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- app/(auth)/sign-in.tsx (outline) ---'
ast-grep outline 'app/(auth)/sign-in.tsx' --view expanded || true

echo
echo '--- relevant lines in app/(auth)/sign-in.tsx ---'
nl -ba 'app/(auth)/sign-in.tsx' | sed -n '1,180p'

echo
echo '--- search for needs_client_trust / sendEmailCode / verification screen ---'
rg -n 'needs_client_trust|sendEmailCode|email_code|verificationError|Enter the code sent to your email|auth-error' app -S || true

Repository: saikumarbt/react-native-recurly

Length of output: 411


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- app/(auth)/sign-in.tsx (1-220 with line numbers) ---'
awk '{printf("%4d %s\n", NR, $0)}' 'app/(auth)/sign-in.tsx' | sed -n '1,220p'

echo
echo '--- targeted search in app/ ---'
rg -n 'needs_client_trust|sendEmailCode|email_code|verificationError|Enter the code sent to your email|auth-error' app -S || true

Repository: saikumarbt/react-native-recurly

Length of output: 9014


Guard the email-code challenge before switching to the verification screen.
If email_code isn’t offered or sendEmailCode() fails, the sign-in flow still lands on the verify step with no way to continue or recover.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(auth)/sign-in.tsx around lines 46 - 53, The sign-in flow in the
needs_client_trust branch can advance to the verification screen even when the
email-code challenge is unavailable or sendEmailCode() fails. Update the sign-in
handler around signIn.status, emailCodeFactor, and signIn.mfa.sendEmailCode() so
the verification step is reached only after confirming the email_code factor
exists and the challenge request succeeds; otherwise stop the transition and
surface a recoverable error or fallback path.

Comment thread app/(auth)/sign-up.tsx
Comment on lines +31 to +32
if (error) {
console.error(JSON.stringify(error, null, 2));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='app/(auth)/sign-up.tsx'
wc -l "$FILE"
cat -n "$FILE" | sed -n '1,140p'

Repository: saikumarbt/react-native-recurly

Length of output: 5604


🌐 Web query:

Clerk Expo signUp object currentTask session.currentTask documentation properties sensitive logging

💡 Result:

In Clerk Expo and related SDKs, session tasks and sign-up objects handle authentication flows with the following characteristics: Session and currentTask The Session object contains a currentTask property [1], which represents a pending session task that must be completed before a session can be fully activated [2]. If a session has a pending task, it remains in a pending state and generally cannot access protected resources [2]. You can access the session object using the useSession hook and check the currentTask property to determine if the user needs to complete further steps (e.g., MFA or profile completion) [1][2]. SignUp Object The SignUp object manages the lifecycle of a sign-up attempt [3]. It tracks status (e.g., complete, missing_requirements) and provides properties to manage identification fields (like email or phone number) and metadata [3][4][5]. A newer, experimental SignUpFuture object is also available for use in custom flows, offering a different API for driving account creation [4][5]. When a sign-up process is complete, its createdSessionId can be used to finalize the session [6][3]. Sensitive Logging Clerk provides mechanisms for debugging and telemetry, but users should be cautious regarding sensitive data: 1. Debug Logging: Clerk has introduced a debug logging subsystem (debugLogger) that provides insights into events like load, navigation, and session activation [7]. Because these logs may contain identifiers (user IDs, session IDs) or context data, care should be taken when using features that forward these to external endpoints [7]. 2. Telemetry: Clerk collects telemetry data for product improvements, which is strictly audited to exclude sensitive information like passwords, tokens, raw file contents, or PII [8][9]. You can opt out of telemetry using environment variables (e.g., CLERK_TELEMETRY_DISABLED=1) or the telemetry prop on the ClerkProvider component [8][9]. 3. Application Logs: The Clerk Dashboard's Application Logs page tracks security-relevant events (e.g., sign_in.completed) [10]. These logs are designed for auditing and debugging, and you should ensure that any custom logging you implement in your application does not inadvertently expose sensitive user information [10].

Citations:


Avoid logging raw Clerk auth state. error, session.currentTask, and signUp can expose identifiers and verification/session details; keep these logs out of production and replace them with a short dev-only message.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(auth)/sign-up.tsx around lines 31 - 32, The sign-up error handling
currently logs raw Clerk auth state, which can expose sensitive identifiers and
session details. In the sign-up flow, update the `error` logging around the
`signUp` / `session.currentTask` checks to use a short dev-only message instead
of serializing the objects directly. Keep any debugging output gated behind a
development-only condition so nothing sensitive is emitted in production.

Comment thread app/(auth)/sign-up.tsx
return;
}

if (!error) await signUp.verifications.sendEmailCode();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Handle the Clerk state before requesting a code. If signUp.password() can already complete, finalize there; only call sendEmailCode() when missing_requirements includes an unverified email_address, otherwise this sign-up flow can stall on non-verification requirements.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(auth)/sign-up.tsx at line 36, The sign-up flow in sign-up.tsx currently
sends an email code unconditionally after signUp.password(), which can stall
when the remaining missing_requirements are not an unverified email address.
Update the logic around signUp.password() and
signUp.verifications.sendEmailCode() to first inspect the Clerk state: if
signUp.password() can already complete, finalize the flow there, and only call
sendEmailCode() when missing_requirements explicitly includes an unverified
email_address. Use the existing signUp, missing_requirements, and sendEmailCode
symbols to place the fix in the correct branch.

Comment thread app/(auth)/sign-up.tsx
Comment on lines +99 to +102
<Pressable
className="auth-secondary-button mt-4"
onPress={() => signUp.verifications.sendEmailCode()}
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and inspect the relevant region.
git ls-files 'app/(auth)/sign-up.tsx'
wc -l app/(auth)/sign-up.tsx
sed -n '1,180p' app/(auth)/sign-up.tsx

Repository: saikumarbt/react-native-recurly

Length of output: 245


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='app/(auth)/sign-up.tsx'

printf '\n== file exists ==\n'
git ls-files -- "$file"

printf '\n== line count ==\n'
wc -l -- "$file"

printf '\n== excerpt ==\n'
sed -n '1,220p' -- "$file"

printf '\n== search for resend and fetch status ==\n'
rg -n 'sendEmailCode|fetchStatus|disabled=' -- "$file"

Repository: saikumarbt/react-native-recurly

Length of output: 7782


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect surrounding symbols to understand whether the button is already guarded elsewhere.
ast-grep outline 'app/(auth)/sign-up.tsx' --view expanded

Repository: saikumarbt/react-native-recurly

Length of output: 280


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='app/(auth)/sign-up.tsx'

printf '\n== excerpt around the button ==\n'
sed -n '70,130p' -- "$file"

printf '\n== grep for related state/handlers in file ==\n'
rg -n 'fetchStatus|signUp|verifications|sendEmailCode|disabled|loading|isLoading|pending|inFlight' -- "$file"

Repository: saikumarbt/react-native-recurly

Length of output: 3421


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='app/(auth)/sign-up.tsx'

printf '\n== excerpt around the button ==\n'
sed -n '1,220p' -- "$file"

printf '\n== symbols in the file ==\n'
rg -n 'fetchStatus|sendEmailCode|verifications|disabled|onPress|useState|useEffect|signUp' -- "$file"

Repository: saikumarbt/react-native-recurly

Length of output: 8350


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for other resend-code implementations in the repo for comparison.
rg -n 'sendEmailCode\(\)|verifications\.sendEmailCode|resend.*code|email code' .

Repository: saikumarbt/react-native-recurly

Length of output: 425


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the target component in smaller chunks to avoid the shell parsing issue.
file='app/(auth)/sign-up.tsx'

printf '\n== 1-140 ==\n'
sed -n '1,140p' -- "$file"

printf '\n== 141-260 ==\n'
sed -n '141,260p' -- "$file"

Repository: saikumarbt/react-native-recurly

Length of output: 7058


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='app/(auth)/sign-up.tsx'

# Show the exact lines around the resend button with line numbers.
nl -ba -- "$file" | sed -n '85,115p'

# Check whether this file already tracks a pending/error state for email-code resend.
rg -n 'error|pending|loading|disabled|sendEmailCode|verifications' -- "$file"

Repository: saikumarbt/react-native-recurly

Length of output: 209


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Compare with any other sign-up or verification flows that handle resend/sendEmailCode.
rg -n 'sendEmailCode|send.*code|resend.*code|verification' app components src

Repository: saikumarbt/react-native-recurly

Length of output: 712


🌐 Web query:

Clerk signUp.verifications.sendEmailCode promise reject duplicate request in-flight resend code behavior

💡 Result:

When using Clerk's signUp.verifications.sendEmailCode() method, there is no built-in "promise rejection" specifically for "duplicate requests in-flight" that prevents the API call from executing. The method initiates a network request to the Clerk Frontend API to prepare the verification strategy [1][2][3]. Historically, Clerk has faced issues where multiple verification codes were triggered unintentionally, such as during component re-mounts, page refreshes, or React Strict Mode re-renders [4][5][6]. Recent updates, including PR #8548 (May 2026), have introduced deduplication logic to the Clerk UI components to prevent unnecessary re-preparation of pending verifications [7]. Key behaviors regarding duplicate or in-flight requests include: 1. Request Execution: Calling sendEmailCode() will generally trigger a network request [1][8]. If you call it multiple times manually (e.g., via rapid button clicks), the SDK will send multiple requests to the API, which may result in multiple emails being sent [9][10]. 2. SDK Deduplication: As of May 2026, Clerk's prebuilt UI components are designed to check the state of the existing signUp or signIn resource before calling "prepare" methods [7]. If a pending (unverified) verification is already present, these components will skip the automatic preparation to avoid sending a new code unless the user explicitly triggers a "Resend" action [7]. 3. Manual Implementation: If you are building a custom flow, the SDK does not automatically deduplicate multiple calls made by your code [9][10]. It is recommended to manage the "loading" or "in-flight" state manually in your application code—for example, by disabling the "Resend" button or tracking the request status—to prevent users from triggering multiple parallel requests [8]. 4. API Behavior: Calling prepare methods while a verification is already active usually invalidates the previous code and triggers a new one [9]. Relying on the API to handle deduplication is not recommended; client-side throttling or state management is the standard approach to ensure only one request is sent at a time [9][8]. To prevent duplicate codes in custom implementations, ensure your code checks the status of the signUp resource or manages a local loading state before executing the promise returned by sendEmailCode() [8].

Citations:


Disable the resend action while sendEmailCode() is in flight. It can fire duplicate requests on repeated taps, and failures should surface a local error instead of failing silently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(auth)/sign-up.tsx around lines 99 - 102, The resend action in the
sign-up flow is not guarded, so repeated taps on the Pressable can trigger
duplicate sendEmailCode() requests and swallow failures. Update the
signUp.verifications.sendEmailCode handler to track an in-flight/loading state,
disable the Pressable while the request is pending, and catch errors so they
surface as a local error state instead of failing silently.

Comment thread app/(tabs)/index.tsx Outdated
Comment thread app/(tabs)/settings.tsx
Comment on lines +13 to +15
const displayName = user?.firstName || user?.fullName || user?.emailAddresses[0]?.emailAddress?.split("@")[0] || "User";
const email = user?.emailAddresses[0]?.emailAddress || "No email";
const memberSince = user?.createdAt ? dayjs(user.createdAt).format("MMMM D, YYYY") : "Recently";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the referenced files and inspect the relevant lines.
git ls-files 'app/(tabs)/*.tsx' | sed 's#^`#FILE` #'

echo
echo '--- app/(tabs)/settings.tsx ---'
cat -n 'app/(tabs)/settings.tsx' | sed -n '1,120p'

echo
echo '--- app/(tabs)/index.tsx ---'
cat -n 'app/(tabs)/index.tsx' | sed -n '1,120p'

echo
echo '--- Search for Clerk email fields ---'
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'primaryEmailAddress|emailAddresses\[0\]|fullName|firstName' .

Repository: saikumarbt/react-native-recurly

Length of output: 8589


🌐 Web query:

Clerk UserResource primaryEmailAddress emailAddresses ordering first item primary email address

💡 Result:

In Clerk's User object, the emailAddresses property is an array of all email addresses associated with the user [1][2]. This array is not guaranteed to be ordered in any specific way, such as placing the primary email address at the first index [1][2]. To reliably retrieve the primary email address from the User object, you should use the primaryEmailAddress property (if available in your environment) or derive it using the primaryEmailAddressId [1][3][4]. When using the Clerk frontend SDKs (e.g., in React), the User object typically includes a primaryEmailAddress property that directly points to the primary EmailAddressResource [1][4]. When using backend SDKs or environments where primaryEmailAddress is not provided, you can identify the primary email by matching the primaryEmailAddressId against the emailAddresses array [4]: const primaryEmail = user.emailAddresses.find( (email) => email.id === user.primaryEmailAddressId); This approach ensures you correctly identify the primary email regardless of its position within the emailAddresses array [4].

Citations:


Use the primary email instead of emailAddresses[0]. emailAddresses is an unordered list, so the first item can be the wrong address for multi-email users. app/(tabs)/index.tsx:31 uses the same fallback-name pattern and should follow the same source.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(tabs)/settings.tsx around lines 13 - 15, The fallback display name and
email lookup in settings are using emailAddresses[0], which can pick the wrong
address for users with multiple emails. Update the settings screen logic around
the displayName and email values to use the primary email source instead of the
first entry, and apply the same fallback-name pattern used in
app/(tabs)/index.tsx so both places resolve identity from the same reliable
field.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/_layout.tsx (1)

29-35: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Duplicate if (!fontsLoaded) return null; block.

Lines 29-31 and 33-35 are identical guards; the second is dead code left over from editing.

♻️ Proposed fix
   if (!fontsLoaded) {
     return null;
   }
 
-  if (!fontsLoaded) {
-    return null;
-  }
-
   const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/_layout.tsx` around lines 29 - 35, There is a duplicated fonts-loaded
guard in the _layout component: the second identical `if (!fontsLoaded) return
null;` block is dead code. Remove the redundant duplicate and keep only one
early return in the layout logic so the component continues after `fontsLoaded`
is true.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@app/_layout.tsx`:
- Around line 29-35: There is a duplicated fonts-loaded guard in the _layout
component: the second identical `if (!fontsLoaded) return null;` block is dead
code. Remove the redundant duplicate and keep only one early return in the
layout logic so the component continues after `fontsLoaded` is true.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 54b20335-9146-4e0f-9119-0aa394bd77cb

📥 Commits

Reviewing files that changed from the base of the PR and between 152915b and 7864dd4.

📒 Files selected for processing (2)
  • .env.example
  • app/_layout.tsx

@saikumarbt
saikumarbt merged commit 0ec0333 into main Jul 3, 2026
1 check passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant