Search code examples
reactjsmaterial-uitextfield

Changing MUI TextField helper text clears value


I have a MUI dialog that asks for a user's info: (full JSfiddle: https://jsfiddle.net/1gfkco6d/1/)

function UserInfoDialog(props) {
    const [nameErrorMsg, setNameErrorMsg] = useState(null);
    const [emailErrorMsg, setEmailErrorMsg] = useState(null);
    const [phoneErrorMsg, setPhoneErrorMsg] = useState(null);

    var result = {};

    const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g;
    const phoneRegex = /^(\+\d{1,2}\s?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/g;

    const onSubmit = () => {
        console.log("result:", result);

        if (!result.name) {
            setNameErrorMsg("Name is required");
            return;
        }
        else {
            setNameErrorMsg(null);
        }

        if (!result.email && !result.phone) {
            setEmailErrorMsg("Either phone or email is required");
            setPhoneErrorMsg("Either phone or email is required");
            return;
        }
        else if (result.email && !emailRegex.test(result.email)) {
            setEmailErrorMsg("Please enter a valid email address");
            return;
        }
        else if (result.phone && !phoneRegex.test(result.phone)) {
            setPhoneErrorMsg("Please enter a valid phone number");
            return;
        }
        else {
            setEmailErrorMsg(null);
            setPhoneErrorMsg(null);
        }

        //Todo: submit the result
        props.onClose();
    };

    return (
        <Dialog open={props.open} onClose={() => props.onClose()}>
            <DialogContent>
                <h4>Please fill out the following information so we can get you connected</h4>
                <TextField autoFocus fullWidth margin="dense" label="Name" variant="standard"
                    helperText={nameErrorMsg} error={nameErrorMsg != null}
                    onChange={e => result.name = e.target.value}/>
                <TextField fullWidth margin="dense" label="Email" variant="standard"
                    helperText={emailErrorMsg} error={emailErrorMsg != null}
                    onChange={e => result.email = e.target.value}/>
                <TextField fullWidth margin="dense" label="Phone" variant="standard"
                    helperText={phoneErrorMsg} error={phoneErrorMsg != null}
                    onChange={e => result.phone = e.target.value}/>
            </DialogContent>
            <DialogActions>
              <Button onClick={() => props.onClose()}>Cancel</Button>
              <Button onClick={() => onSubmit()}>Submit</Button>
            </DialogActions>
        </Dialog>
    );
  }

But when I click the "submit" button twice it clears the props of the result object. I've found if I remove all the validation checking this doesn't happen - but obviously I want the validation.

enter image description here

Any ideas?


Solution

  • I have fixed your fiddle for you: https://jsfiddle.net/vyouqcd5/

    Issues you had:

    1. Instead of using var result, I have created a state variable
    const [result, setResult] = useState({})
    

    The reason I made this a state variable is because, after you update your error state variables in onSubmit callback, React will cause the component to be re-rendered. At that time, result will be created again with {} value, which is the root cause of your issue.

    1. Updated the onChange handler of the text fields to update this state variable, like:
    onChange={e => onChange(e.target.value, 'name')}/>
    
    1. Updated the initial value of error state variables:
    const [nameErrorMsg, setNameErrorMsg] = useState();
    const [emailErrorMsg, setEmailErrorMsg] = useState();
    const [phoneErrorMsg, setPhoneErrorMsg] = useState();
    

    enter image description here