Logré refactorizar el código y conseguí que resultara. Comparto el código (dejé las funciones validadoras en un archivo JS aparte):
import React, { useState } from "react";
import {
Button,
TextField,
Switch,
FormGroup,
FormControlLabel,
} from "@mui/material";
import {
validateName,
validateEmail,
validateLastName,
} from "./validations.js";
export default function Form() {
const [name, setName] = useState({ value: "", valid: null });
const [lastName, setLastName] = useState({ value: "", valid: null });
const [email, setEmail] = useState({ value: "", valid: null });
const [proms, setProms] = useState(true);
const [novs, setNovs] = useState(true);
const newUser = {
name,
lastName,
email,
proms,
novs,
};
const handleSubmit = ({ name, lastName, email }) => {
if (name.valid && lastName.valid && email.valid) {
alert(`Bienvenido ${name.value} ${lastName.value}`);
} else if (name.value === "") {
setName({ value: name.value, valid: false });
} else if (lastName.value === "") {
setLastName({ value: lastName.value, valid: false });
} else if (email.value === "") {
setEmail({ value: email.value, valid: false });
}
};
return (
<>
<form
onSubmit={(e) => {
e.preventDefault();
handleSubmit(newUser);
}}
>
<TextField
id="outlined-basic"
label="Nombre"
variant="outlined"
fullWidth
margin="normal"
value={name.value}
error={name.valid === false}
helperText={
name.valid === false
? "El nombre debe tener mínimo 3 carácteres"
: ""
}
onChange={(e) => {
const inputName = e.target.value;
setName({ value: inputName, valid: validateName(inputName) });
}}
/>
<TextField
id="outlined-basic"
label="Apellidos"
variant="outlined"
fullWidth
margin="normal"
value={lastName.value}
error={lastName.valid === false}
helperText={
lastName.valid === false
? "El apellido debe tener mínimo 3 carácteres"
: ""
}
onChange={(e) => {
const inputLastName = e.target.value;
setLastName({
value: inputLastName,
valid: validateLastName(inputLastName),
});
}}
/>
<TextField
id="outlined-basic"
label="Email"
variant="outlined"
fullWidth
margin="normal"
value={email.value}
error={email.valid === false}
helperText={email.valid === false ? "Ingrese un email válido" : ""}
onChange={(e) => {
const inputEmail = e.target.value;
setEmail({ value: inputEmail, valid: validateEmail(inputEmail) });
}}
/>
<FormGroup>
<FormControlLabel
control={<Switch />}
label="Promociones"
checked={proms}
onChange={(e) => {
setProms(e.target.checked);
}}
/>
<FormControlLabel
control={<Switch />}
label="Novedades"
checked={novs}
onChange={(e) => {
setNovs(e.target.checked);
}}
/>
</FormGroup>
<Button variant="contained" type="submit">
Registrarse
</Button>
</form>
</>
);
}
Aquí las funciones validadoras:
export const validateName = (name) => {
if (name.length > 3 && name !== "") {
return true;
} else {
return false;
}
};
export const validateLastName = (lastName) => {
if (lastName.length > 3 && lastName !== "") {
return true;
} else {
return false;
}
};
export const validateEmail = (email) => {
if (email.length > 3 && email !== "") {
return true;
} else {
return false;
}
};
Decidí dejar fuera el state de errores para manejarlos desde cada estado de los inputs de usuario.