Skip to content

fix: re-run transformer on transformerId prop change#5

Merged
janicduplessis merged 1 commit intomainfrom
@janic/auto-reformat-on-transformer-change
Apr 25, 2026
Merged

fix: re-run transformer on transformerId prop change#5
janicduplessis merged 1 commit intomainfrom
@janic/auto-reformat-on-transformer-change

Conversation

@janicduplessis
Copy link
Copy Markdown
Contributor

@janicduplessis janicduplessis commented Apr 25, 2026

Description

When a consumer swaps the transformer prop on TransformerTextInput (e.g., a currency picker switching between USD/EUR/JPY instances), the native decorator only registered the new transformer in the registry — it did not re-run it on the existing displayed text. The user would see the old formatting until they typed a keystroke, at which point the new transformer would finally run. The example app worked around this with a useEffect([currency]) that called inputRef.current.update({ transform: true }) after every picker change.

Solution

iOS and Android both detect the transformerId change at the same place they already update the registry lookup, and additionally re-run the new transformer on the current text + selection when the change happens after mount. If the resulting value or selection differs, they apply it (and on iOS, notify the base text-input delegate so React's onChangeText fires once).

The initial prop set is excluded by checking that the previous transformerId was non-zero (the default before the first React-driven set) and that the backing text-input view is attached. The JS-side transformedDefaultValue continues to own the very first render.

The example app drops its useEffect workaround — switching the currency picker reformats the displayed amount on its own now.

Test plan

  • Pod install + rebuild iOS, gradle rebuild Android (native code changed).
  • In the example app, open the Currency card, type a few digits (e.g., 1234567\$12,345.67).
  • Switch the picker to EUR — expect the displayed value to immediately reformat to 12.345,67 €.
  • Switch to JPY — expect ¥1,234,567 (no decimals, all whole units).
  • Switch back to USD — expect \$12,345.67 again.
  • Confirm the keyboard cursor lands right after the last digit in each currency, and that subsequent typing still works as expected.

The native decorator view only registered the new transformer when the
prop changed; the existing displayed text was not re-transformed until
the next keystroke. This forced consumers to call update({transform:true})
themselves whenever they swapped transformer instances (e.g., a currency
picker switching between USD/EUR/JPY).

iOS and Android now detect a transformerId change after mount and
re-run the new transformer on the current value, applying any new
formatting and selection. The initial prop set is excluded so the
JS-side defaultValue pre-transform still owns the first render.

The example app's currency picker drops its useEffect workaround.
@janicduplessis janicduplessis force-pushed the @janic/auto-reformat-on-transformer-change branch from 2230f97 to e4302f0 Compare April 25, 2026 21:45
@janicduplessis janicduplessis merged commit 156253a into main Apr 25, 2026
10 checks passed
@janicduplessis janicduplessis deleted the @janic/auto-reformat-on-transformer-change branch April 25, 2026 21:47
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