Skip to content

Added revalidation of inputs on change.#33

Open
SajidMannikeri17 wants to merge 1 commit into
thunder-id:mainfrom
Infosys:fix/revalidate-on-change
Open

Added revalidation of inputs on change.#33
SajidMannikeri17 wants to merge 1 commit into
thunder-id:mainfrom
Infosys:fix/revalidate-on-change

Conversation

@SajidMannikeri17

@SajidMannikeri17 SajidMannikeri17 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Purpose

Fixes thunder-id/thunderid#3145. Inline validation errors in SignIn / SignUp / Recovery currently persist while the user corrects their input and only clear on blur. Adds an opt-in prop revalidateOnChangeAfterBlur on those components so a rendered error clears the moment the value becomes valid. Also fixes a stale-values closure bug inside useForm that would otherwise cause a one-keystroke lag when on-change validation runs.

<SignIn revalidateOnChangeAfterBlur />
<SignUp revalidateOnChangeAfterBlur />
<Recovery revalidateOnChangeAfterBlur />

Approach

useForm refactor

  • Extracted computeFieldError(value, fieldConfig, requiredMessage) as a pure helper — takes the value as an argument instead of reading a closed-over values state.
  • setValue now validates against the next value via computeFieldError, fixing the one-keystroke lag caused by validateField reading pre-update state after setFormValues(prev => …) queued its update.
  • New config revalidateOnChangeAfterBlur?: boolean (default false). When enabled, setValue re-runs validation only if touched[name] === true, so errors don't appear while initially typing — only while correcting after the first blur.
  • validateField (blur path) unchanged in behavior; delegates to computeFieldError internally.

Prop plumbing

  • Added revalidateOnChangeAfterBlur?: boolean (default false) to BaseSignInProps, BaseSignUpProps, BaseRecoveryProps; passed to their internal useForm calls.
  • SignUp / Recovery inherit the prop via existing BaseXProps & intersections + {...rest} forwarding.
  • SignIn uses an explicit SignInProps, so the prop was added and forwarded to <BaseSignIn> explicitly.

Backward compatibility

  • Default false at every layer — no consumer sees a change unless they opt in.
  • Stale-values fix only affects the on-change validation path, which is gated behind validateOnChange or revalidateOnChangeAfterBlur.
  • No public exports removed or renamed. validateOnChange and revalidateOnChangeAfterBlur are independent.

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added an optional revalidateOnChangeAfterBlur flag for sign-in, sign-up, and account recovery forms to re-run validation on subsequent typing after a blur event (defaults to preserving existing behavior).
    • Extended the shared form hook to support this consistently, including improved per-field validation calculation.
  • Bug Fixes

    • Improved embedded sign-in terminal error handling to better preserve or clear flow state as appropriate, and removed an unnecessary throw.
  • Behavior Changes

    • Form field generation now includes custom input types for validation where applicable.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 45 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ba619564-d978-4df8-81d8-79882a93a6c8

📥 Commits

Reviewing files that changed from the base of the PR and between e1d4487 and b6956ae.

📒 Files selected for processing (5)
  • packages/react/src/components/presentation/auth/Recovery/BaseRecovery.tsx
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx
  • packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/hooks/useForm.ts
📝 Walkthrough

Walkthrough

Authentication form components now expose revalidateOnChangeAfterBlur, default it to false, and pass it to useForm. Sign-in also includes custom form components and distinguishes recoverable embedded-flow errors from terminal responses before normalization.

Changes

Authentication form behavior

Layer / File(s) Summary
Form validation policy
packages/react/src/hooks/useForm.ts
useForm centralizes field error computation and revalidates touched fields against the next value when enabled.
Authentication component wiring
packages/react/src/components/presentation/auth/{Recovery,SignIn,SignUp}/*
Authentication components expose and forward the option; sign-in also includes CUSTOM components in field extraction.
Sign-in terminal response handling
packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
Recoverable errors preserve execution state and set flowError; terminal responses clear state, set errors, clean URL parameters, and stop before normalization.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AuthForm
  participant useForm
  User->>AuthForm: type after blur
  AuthForm->>useForm: setValue(nextValue)
  useForm->>useForm: validate touched field
  useForm-->>AuthForm: update or clear error
Loading

Possibly related PRs

Suggested reviewers: brionmario

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The SignIn terminal-response and initialization changes are unrelated to the validation revalidation issue. Remove the SignIn flow-error/terminal-response behavior changes or split them into a separate PR focused on that concern.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding revalidation of inputs on change.
Description check ✅ Passed The PR description covers Purpose, Approach, Related Issues, Related PRs, and the required checklist sections well enough.
Linked Issues check ✅ Passed The changes address #3145 by revalidating after blur so validation errors clear when corrected input becomes valid.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Caution

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

⚠️ Outside diff range comments (1)
packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx (1)

591-595: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove hardcoded thunderid literal from data-testid attributes.

As per path instructions, avoid hardcoding the vendor name thunderid in DOM data-* attributes. Since this is an internal test identifier and the brand prefix is likely not load-bearing, the best fix is to avoid the vendor prefix entirely and use data-testid="signin". If a brand-scoped namespace is genuinely required by external testing frameworks, use ${getVendorPrefix(vendor)}-signin instead.

  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx#L591-L595: replace data-testid="thunderid-signin" with data-testid="signin".
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx#L601-L606: replace data-testid="thunderid-signin" with data-testid="signin".
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx#L618-L623: replace data-testid="thunderid-signin" with data-testid="signin".
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx#L634-L639: replace data-testid="thunderid-signin" with data-testid="signin".
🤖 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 `@packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx` around
lines 591 - 595, Remove the hardcoded vendor prefix from all four data-testid
attributes in BaseSignIn:
packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx at lines
591-595, 601-606, 618-623, and 634-639. Set each identifier to the unprefixed
signin value; no other rendering behavior needs to change.

Source: Path instructions

🧹 Nitpick comments (1)
packages/react/src/hooks/useForm.ts (1)

320-329: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Prevent unnecessary state updates when the field error remains unchanged.

When shouldValidate is true, setFormErrors currently creates and returns a new object on every keystroke, even if the error for the field hasn't changed. Returning the existing state object when there's no change allows React to bail out of unnecessary re-renders.

♻️ Proposed refactor to bail out of state updates
       const error: string | null = computeFieldError(value, getFieldConfig(name), requiredMessage);
       setFormErrors((prev: Record<keyof T, string>) => {
+        if (prev[name] === error || (!error && !(name in prev))) {
+          return prev;
+        }
         const newErrors: Record<keyof T, string> = {...prev};
         if (error) {
           newErrors[name] = error;
🤖 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 `@packages/react/src/hooks/useForm.ts` around lines 320 - 329, Update the
setFormErrors callback in the shouldValidate path to compare the current error
for name with the newly computed error before cloning state. Return the existing
prev object when the field’s error is unchanged; otherwise preserve the current
add/remove behavior using a copied error map.
🤖 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 `@packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx`:
- Around line 591-595: Remove the hardcoded vendor prefix from all four
data-testid attributes in BaseSignIn:
packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx at lines
591-595, 601-606, 618-623, and 634-639. Set each identifier to the unprefixed
signin value; no other rendering behavior needs to change.

---

Nitpick comments:
In `@packages/react/src/hooks/useForm.ts`:
- Around line 320-329: Update the setFormErrors callback in the shouldValidate
path to compare the current error for name with the newly computed error before
cloning state. Return the existing prev object when the field’s error is
unchanged; otherwise preserve the current add/remove behavior using a copied
error map.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 50a0fcd0-cae2-4355-8cd9-b32884e12d2a

📥 Commits

Reviewing files that changed from the base of the PR and between a02382f and 3617dcf.

📒 Files selected for processing (5)
  • packages/react/src/components/presentation/auth/Recovery/BaseRecovery.tsx
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx
  • packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/hooks/useForm.ts

@SajidMannikeri17
SajidMannikeri17 force-pushed the fix/revalidate-on-change branch from 3617dcf to 50b522c Compare July 20, 2026 09:49

@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: 1

🧹 Nitpick comments (1)
packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx (1)

282-294: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move acceptableType outside the component.

Recreating this array on every render violates React dependency rules because it is referenced inside the extractFormFields useCallback but omitted from its dependency array. Moving the constant outside the component resolves the dependency issue and avoids unnecessary allocations.

Define the array outside the component:

const ACCEPTABLE_TYPES = [
  'TEXT_INPUT',
  'PASSWORD_INPUT',
  'EMAIL_INPUT',
  'PHONE_INPUT',
  'OTP_INPUT',
  'SELECT',
  'DATE_INPUT',
  'CUSTOM',
];
♻️ Proposed refactor
-  /**
-     * Component type for which forms validation will be applicable
-    */
-  const acceptableType = [
-    'TEXT_INPUT',
-    'PASSWORD_INPUT',
-    'EMAIL_INPUT',
-    'PHONE_INPUT',
-    'OTP_INPUT',
-    'SELECT',
-    'DATE_INPUT',
-    'CUSTOM',
-  ];

And update its usage below:

-          if (acceptableType.includes(component.type)) {
+          if (ACCEPTABLE_TYPES.includes(component.type)) {
🤖 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 `@packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx` around
lines 282 - 294, Move the acceptableType array out of the component scope,
rename it to ACCEPTABLE_TYPES, and update extractFormFields and any other
references to use the module-level constant so useCallback dependencies remain
stable.
🤖 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 `@packages/react/src/components/presentation/auth/SignIn/SignIn.tsx`:
- Around line 447-466: Update handleTerminalResponse so terminal error responses
clear state, set the error, and clean up URL parameters, then return true
instead of throwing. Preserve the existing recoverable-error behavior and ensure
initializeFlow and handleSubmit do not enter their catch paths for this handled
terminal response.

---

Nitpick comments:
In `@packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx`:
- Around line 282-294: Move the acceptableType array out of the component scope,
rename it to ACCEPTABLE_TYPES, and update extractFormFields and any other
references to use the module-level constant so useCallback dependencies remain
stable.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: caba69a6-d5ce-4c88-8470-bf439859d14b

📥 Commits

Reviewing files that changed from the base of the PR and between 3617dcf and 50b522c.

📒 Files selected for processing (5)
  • packages/react/src/components/presentation/auth/Recovery/BaseRecovery.tsx
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx
  • packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/hooks/useForm.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/hooks/useForm.ts

Comment thread packages/react/src/components/presentation/auth/SignIn/SignIn.tsx Outdated
@SajidMannikeri17
SajidMannikeri17 force-pushed the fix/revalidate-on-change branch 2 times, most recently from 1d96bcf to b0ce359 Compare July 20, 2026 10:47
@ThaminduDilshan

Copy link
Copy Markdown
Member

@SajidMannikeri17 did we test that this fix works and won't cause other issues like call depth exceeding?

@SajidMannikeri17

SajidMannikeri17 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Yes @ThaminduDilshan. We have tested these changes locally via symlink. There are no issues.

@brionmario

Copy link
Copy Markdown
Member

Hey @SajidMannikeri17,

Seems like the formatting linter is failing.
execute pnpm format:fix from the root to run prettier.

@SajidMannikeri17
SajidMannikeri17 force-pushed the fix/revalidate-on-change branch from b0ce359 to e1d4487 Compare July 22, 2026 12:29
@SajidMannikeri17

Copy link
Copy Markdown
Contributor Author

Hi @brionmario. Fixed the linter. Please check.

@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: 1

🤖 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 `@packages/react/src/components/presentation/auth/SignIn/SignIn.tsx`:
- Around line 606-607: Restrict the initializationAttemptedRef reset in
handleTerminalResponse to unrecoverable Error responses only. Do not reset the
gate for Complete responses, including successful completion without a redirect
URL, so clearing flow state cannot trigger a new sign-in flow.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3cf33985-1f7b-4ee7-9ecc-b3e252d9ba52

📥 Commits

Reviewing files that changed from the base of the PR and between 50b522c and e1d4487.

📒 Files selected for processing (5)
  • packages/react/src/components/presentation/auth/Recovery/BaseRecovery.tsx
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx
  • packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/hooks/useForm.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/react/src/components/presentation/auth/Recovery/BaseRecovery.tsx
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/hooks/useForm.ts
  • packages/react/src/components/presentation/auth/SignIn/BaseSignIn.tsx

Comment thread packages/react/src/components/presentation/auth/SignIn/SignIn.tsx Outdated
Signed-off-by: Sajid Mannikeri <sajid.mannikeri@ad.infosys.com>
@SajidMannikeri17
SajidMannikeri17 force-pushed the fix/revalidate-on-change branch from e1d4487 to b6956ae Compare July 22, 2026 12:45
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.

Input validation error does not clear dynamically while typing from thunder react SDK

3 participants