If you’ve spent any time building forms in React Native with React Hook Form and validation libraries like Zod or Yup, you’ve likely encountered a strange phenomenon: the "Disappearing Zero."
One minute you're building a sleek checkout or progress flow, and the next, your users are complaining that every time they try to enter 0, the input field just... wipes itself clean.
The culprit? JavaScript’s definition of "falsy."
The Trap: JavaScript Falsiness
In React Native, numeric inputs often start as null or undefined (or a number type in your state). Since TextInput (or custom Input components) expect a string, a common pattern is to cast the value like this:
// ❌ The Buggy Way
value={value ? String(value) : ''}
On the surface, this looks clean. If there's a value, stringify it; otherwise, show an empty string.
The Gotcha: In JavaScript, 0 is falsy.
When a user types "0", the expression value ? ... evaluates to false, and the input receives an empty string (''). The zero vanishes instantly, leaving your users confused and your validation library potentially complaining about a missing value.
The Solution: Explicit Checks
To fix this, we need to stop relying on loose truthiness and start checking for what we actually care about: whether the value is null or undefined.
// ✅ The Robust Way
value={value !== null && value !== undefined ? String(value) : ''}
By being explicit, we ensure that 0 (which is not null or undefined) is correctly stringified and rendered in the UI.
Real-World Example: React Hook Form + Controller
Here is how this looks in a typical implementation. In this example, we're tracking "Completed Stages," where 0 is a perfectly valid (and common) input.
<Controller
control={control}
name="completedStages"
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Completed Stages"
// The Fix: Ensure 0 is correctly rendered as a string
value={value !== null && value !== undefined ? String(value) : ''}
onChangeText={(text) => {
// Convert back to number for your validation schema (Zod/Yup)
const parsed = parseInt(text, 10);
onChange(isNaN(parsed) ? undefined : parsed);
}}
onBlur={onBlur}
keyboardType="number-pad"
placeholder="5"
error={errors.completedStages?.message}
/>
)}
/>
Why This Matters for Zod and Yup
Validation libraries like Zod and Yup are strict about types. If your UI logic converts a 0 into an empty string (''), your schema validation might fail with a "Required" error or a type mismatch, even though the user intended to enter zero.
By fixing the UI representation, you keep your data flow consistent:
- User enters 0 -> UI sees "0".
-
onChange parses "0" -> Hook Form stores
0. -
Zod/Yup validates
0-> Success!
Summary
In React Native forms, truthiness is often too blunt a tool for numeric inputs. When handling the value prop:
- Avoid
value ? String(value) : '' - Prefer
value !== null && value !== undefined ? String(value) : ''
It’s a tiny change that prevents one of the most common (and annoying) bugs in mobile form development.
Top comments (0)