forms-8-error-handling
Error Handling: Cover how to manage form errors, display error messages, and handle server-side validation errors, using TypeScript to ensure that error handling logic is correctly implemented.
When discussing error handling in React TypeScript forms during an interview, it's important to cover various aspects, such as client-side validation, server-side error handling, and user feedback. Here are ten topics with code examples that you can use to illustrate error handling in forms:
1. Client-Side Validation
Explain how to perform client-side validation and show the TypeScript interface for validation errors.
interface FormValues {
username: string;
password: string;
}
interface FormErrors {
username?: string;
password?: string;
}
const validateForm = (values: FormValues): FormErrors => {
const errors: FormErrors = {};
if (!values.username) errors.username = 'Username is required';
if (!values.password) errors.password = 'Password is required';
return errors;
};
2. Displaying Validation Errors
Discuss how to display validation errors next to each form field and ensure that TypeScript types are used for error objects.
interface InputProps {
name: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
error?: string;
}
const InputField: React.FC<InputProps> = ({ name, value, onChange, error }) => (
<div>
<input name={name} value={value} onChange={onChange} />
{error && <span className="error">{error}</span>}
</div>
);
3. Error Handling with useForm
Show how to integrate error handling within a custom useForm
hook.
const useForm = <T extends FormValues>(initialValues: T) => {
const [values, setValues] = useState<T>(initialValues);
const [errors, setErrors] = useState<FormErrors>({});
// ... other useForm logic
const validate = () => {
const validationErrors = validateForm(values);
setErrors(validationErrors);
return Object.keys(validationErrors).length === 0;
};
return {
values,
handleChange,
handleSubmit,
errors,
validate,
};
};
4. Server-Side Validation Errors
Illustrate how to handle and type server-side validation errors that may be received after form submission.
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (!validate()) return;
try {
// Submit form data
const response = await submitFormData(values);
// Handle successful submission
} catch (error: any) {
if (error.response && error.response.data.errors) {
// Assuming error.response.data.errors is the format the server sends
setErrors(error.response.data.errors);
}
}
};
5. Typing Server-Side Errors
Discuss how TypeScript ensures that the error object structure from the server is what the front end expects.
interface ServerErrors {
[key: string]: string[]; // Assuming server sends errors as an array of strings
}
const handleServerError = (serverErrors: ServerErrors) => {
const formErrors: FormErrors = {};
Object.keys(serverErrors).forEach((key) => {
formErrors[key] = serverErrors[key].join(', '); // Join multiple errors with a comma
});
setErrors(formErrors);
};
6. Inline Error Feedback
Talk about providing inline error feedback as the user types, using TypeScript to track the error state for each field.
// Inside your useForm hook
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
const { name, value } = event.target;
const fieldError = validateField(name, value); // validateField is a function that validates individual fields
setErrors({ ...errors, [name]: fieldError });
};
7. Global Error Messages
Explain how to handle and display global error messages, such as "Form submission failed."
const [globalError, setGlobalError] = useState<string | null>(null);
// Inside your form submission error handling
if (error.response && error.response.data.message) {
setGlobalError(error.response.data.message); // Global error message from the server
}
8. Error Boundary for Submission
Cover the use of error boundaries in React to handle unexpected errors during form submission.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error: Error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong with form submission.</h1>;
}
return this.props.children;
}
}
9. Asynchronous Validation
Discuss the implementation of asynchronous validation, such as checking if a username is taken, and how TypeScript helps manage the state and
types involved.
const checkUsername = async (username: string): Promise<void> => {
// Asynchronous check against server
const isTaken = await isUsernameTaken(username);
if (isTaken) {
setErrors((prevErrors) => ({ ...prevErrors, username: 'Username is already taken' }));
}
};
// Call this function on username field onBlur or onChange as needed
10. Formik and TypeScript
Finally, illustrate how to use Formik with TypeScript to manage form state, validation, and submission, providing robust type safety.
import { useFormik } from 'formik';
const formik = useFormik({
initialValues: {
username: '',
password: '',
},
validate: validateForm,
onSubmit: async (values) => {
try {
// Submit form data
await submitFormData(values);
} catch (error: any) {
handleServerError(error.response.data.errors);
}
},
});
Each of these topics demonstrates a different aspect of error handling in forms, from validation to submission, with TypeScript ensuring that each step is type-safe and properly managed. By discussing these topics, you will demonstrate a thorough understanding of error handling in React forms with TypeScript.