Formularios y Validación
Armamos los formularios con react-hook-form y validamos con zod,
conectados mediante @hookform/resolvers. El schema es la única fuente de
verdad — los tipos de TypeScript del formulario se infieren de él, así que
la validación y los tipos nunca pueden desalinearse.
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Text, TextInput } from "react-native";
const schema = z.object({
email: z.string().email("Ingresá un email válido"),
amount: z.coerce.number().positive("El monto debe ser mayor a 0"),
});
type FormValues = z.infer<typeof schema>;
export function PaymentForm({ onValid }: { onValid: (v: FormValues) => void }) {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<FormValues>({ resolver: zodResolver(schema) });
return (
<>
<Controller
control={control}
name="email"
render={({ field: { onChange, value } }) => (
<TextInput value={value} onChangeText={onChange} autoCapitalize="none" />
)}
/>
{errors.email && <Text>{errors.email.message}</Text>}
{/* submit */}
{/* onPress={handleSubmit(onValid)} */}
</>
);
}
Puntos clave:
- Envolvé cada input nativo en un
Controller(los inputs de React Native no son nodos DOM no controlados, así que RHF necesita el adapter). - Leé los errores desde
formState.errors.<field>?.message. z.coerce.number()convierte el string que produce unTextInputen un número antes de validar.
Consejo
Reusá los schemas de zod más allá de los formularios — validá las respuestas
de la API con el mismo schema (schema.parse(response)) para que los datos
inválidos fallen ruidosamente en el borde, en vez de en algún lugar profundo
de una screen.