Building a Simple Login Form
Create an email and password form that validates input length, shows an error message for invalid entries, and calls a mock login function on submit.
Login Form Requirements
A login form is one of the first screens in almost every mobile app. A good implementation must: render email and password fields, validate input (non-empty, valid email format, minimum password length), show field-level error messages below each input, display a loading indicator during the authentication request, show a server error if credentials are wrong, and successfully navigate to the main app on success. This lesson applies TextInput, controlled components, validation logic, and basic state management in one realistic feature.
// State needed for the login form:
// - email: string
// - password: string
// - emailError: string
// - passwordError: string
// - isLoading: boolean
// - serverError: string
// Derived:
// - isSubmitDisabled: !email || !password || isLoadingForm State and Structure
Set up the form's state variables with useState. Using separate states for each field makes updating and validating them independently straightforward. Group the error messages alongside the input values so validation can set and clear them independently. The isLoading flag disables the submit button and shows a spinner while the authentication network request is in progress, preventing double submissions. Clear the serverError whenever the user changes any input value to give them a fresh start.
import { useState } from 'react';
function useLoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [emailError, setEmailError] = useState('');
const [passwordError, setPasswordError] = useState('');
const [serverError, setServerError] = useState('');
const [isLoading, setIsLoading] = useState(false);
function handleEmailChange(text) {
setEmail(text);
if (serverError) setServerError('');
if (emailError) setEmailError('');
}
function handlePasswordChange(text) {
setPassword(text);
if (serverError) setServerError('');
if (passwordError) setPasswordError('');
}
return { email, password, emailError, passwordError, serverError, isLoading, handleEmailChange, handlePasswordChange, setEmailError, setPasswordError, setServerError, setIsLoading };
}