Repository navigation
underlineColorAndroid silently ignored on initial render with Fabric (New Architecture) #57921
Description
Description
On Android with the New Architecture (Fabric), underlineColorAndroid set as a prop on TextInput is silently dropped on the initial render. The dark material underline remains visible. The prop applies correctly after any subsequent re-render (state change, hot reload).
React Native version: 0.83.x (first version where this is unavoidable — Expo SDK 55 made Fabric mandatory)
Platform: Android only
Architecture: New Architecture (Fabric) only — did not reproduce on Paper/Bridge
Steps to reproduce
<TextInput underlineColorAndroid="transparent" />On initial mount: the native Android underline is visible.
After any re-render: the underline disappears correctly.
Expected behavior
underlineColorAndroid is applied on initial mount, consistent with the old architecture behavior.
Actual behavior
The prop is silently dropped on initial mount. The ReactEditText shows its default material underline.
Root cause
ReactTextInputManager.kt, setUnderlineColor (unchanged between 0.82 and 0.83):
@ReactProp(name = "underlineColorAndroid", customType = "Color")
public fun setUnderlineColor(view: ReactEditText, underlineColor: Int?) {
val background = view.background
if (background == null) {
return // ← prop silently dropped if background not yet populated
}
// ...
}In Fabric, createViewInstance creates the ReactEditText and immediately applies all initial props synchronously. If the view's background drawable is null at that moment (no material theme on the ThemedReactContext, or editTextBackground attr not resolved yet), setUnderlineColor hits the early return and the prop is lost.
A secondary issue: if BackgroundStyleApplicator.setBackgroundColor() runs first, it wraps the original background in a CompositeBackgroundDrawable (LayerDrawable). Calling setColorFilter on a LayerDrawable does not propagate to child drawables in all Android versions, so the underline drawable inside the wrapper is unaffected.
On the update path (re-render), the background is already populated and the color filter applies successfully — which is why subsequent renders work.
Workaround
Call setNativeProps({ underlineColorAndroid }) in a useEffect after mount, which goes through the update path:
const ref = useRef<TextInput>(null)
useEffect(() => {
ref.current?.setNativeProps({ underlineColorAndroid: 'transparent' })
}, [])
<TextInput ref={ref} underlineColorAndroid="transparent" />Suggested fix
In setUnderlineColor, rather than silently returning when background == null, ensure the background drawable is initialized before applying the color filter — either by calling ensureCompositeBackgroundDrawable(view) or by initializing a default background from the EditText theme attribute.
Activity
react-native-bot commentedon Aug 12, 2026
Warning
Missing reproducer: We could not detect a reproducible example in your issue report. Reproducers are mandatory and we can accept only one of those as a valid reproducer:
You can read more about about it on our website: How to report a bug.
nduaarte commentedon Aug 14, 2026
Edit: I spent more time on this and want to walk back my previous comment — I haven't been able to reproduce the bug.
I built RNTester from current
mainand tested on a real device/emulator (API 36, Fabric enabled), using both a bare<TextInput underlineColorAndroid="..." />and one with an explicitborderWidth/borderColor(to force theCompositeBackgroundDrawablewrap beforesetUnderlineColorruns). In every case — cold app start included — the underline color applied correctly on the very first mount.I also added temporary logging directly inside
setUnderlineColor/createViewInstance:view.backgroundwas nevernullat the point the prop setter runs (AppCompatEditTextresolves its themed background synchronously in its own constructor), and the color filter did propagate through theCompositeBackgroundDrawable/LayerDrawablewrapper when present. So neither of the two root causes described above reproduced for me.Since this report is also missing the mandatory reproducer (flagged by the bot above), would you be able to share:
RNTesterPlayground.jsPR or an Expo SnackHappy to take another look once there's something concrete to reproduce against.
Original comment below, kept for context:
Hi! I did some digging into this and I believe your root-cause analysis is spot on, the early return in setUnderlineColor when background == null on the initial mount path definitely looks like the culprit, and the LayerDrawable/setColorFilter propagation issue you flagged as a secondary cause makes sense too.
I'd like to take a shot at implementing your suggested fix (ensuring the background drawable is initialized before applying the color filter, handling both the plain-background case and the CompositeBackgroundDrawable case). I have a full RN + Fabric dev environment set up and can reproduce this reliably with the repro you provided.
Would it be okay if I open a PR for this? Happy to adjust the approach based on any feedback first if you'd prefer.
react-native-bot commentedon Sep 8, 2026
This issue is waiting for author's feedback since 24 days. Please provide the requested feedback or this will be closed in 7 days.
react-native-bot commentedon Sep 15, 2026
This issue was closed because the author hasn't provided the requested feedback after 7 days.