1

I wish to clear all input fields after submitting values in React Application.Please guide me in an easy way. addNurse is the method I used to submit my values to the backend API. Thank you.

import React, { useState } from 'react';
import axios from 'axios';

function NurseAddForm() {
    const url = process.env.REACT_APP_BACKEND_API;

    const [nurseId, setNurseId] = useState(null);
    const [firstName, setFirstName] = useState(null);
    const [lastName, setLastName] = useState(null);
    const [nic, setNic] = useState(null);
    const [password, setPassword] = useState(null);

    const handleSaveChanges = () => {
        if (
            nurseId == null ||
            nurseId === '' ||
            firstName == null ||
            firstName === '' ||
            lastName == null ||
            lastName === '' ||
            nic == null ||
            nic === '' ||
            password == null ||
            password === ''
        ) {
            alert('Error! All the filds should be filled');
        }else if (nic.length !== 10) {
            alert('NIC should be 10  Numbers with V');
        } else if (password.length < 6) {
            alert('Your password must be at least 6 characters');
        } else if (password.search(/[a-z]/) < 0) {
            alert('Your password must contain at least one lowercase letter');
        } else if (password.search(/[A-Z]/) < 0) {
            alert('Your password must contain at least one uppercase letter');
        } else if (password.search(/[0-9]/) < 0) {
            alert('Your password must contain at least one digit');
        } else if (!/^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,25}$/.test(password)) {
            alert('Your password must contain at least one special character');
        } else {
            addNurse();
        }
    };
    const addNurse = () => {
        axios
            .post(url.concat('/api/Nxxxx/'), {
                NurseId: parseInt(nurseId),
                FirstName: firstName,
                LastName: lastName,
                Nic: nic,
                Password: password,
            })
            .then((res) => {
                alert('Saved Successfully');
                console.log(res);
                console.log(res.data);
            })
            .catch((err) => {
                console.log(err);
            });
    };

    return (
        <div className="container">
             <button>
                <a href="/admin/nurse/view">View</a>
            </button>
            <form>
                <div className="form-group">
                    <label>Nurse ID</label>
                    <input
                        type="text"
                        className="form-control"
                        onChange={(e) => setNurseId(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>First Name</label>
                    <input
                        type="text"
                        className="form-control"
                        onChange={(e) => setFirstName(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>Last Name</label>
                    <input
                        type="text"
                        className="form-control"
                        onChange={(e) => setLastName(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>NIC</label>
                    <input
                        type="text"
                        className="form-control"
                        onChange={(e) => setNic(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>Passowrd</label>
                    <input
                        type="password"
                        className="form-control"
                        onChange={(e) => setPassword(e.target.value)}
                    ></input>
                </div>
            </form>
            <button className="btn btn-success" onClick={handleSaveChanges}>
                Save Changes
            </button>
        </div>
    );
}

export default NurseAddForm;

Roshani
  • 41
  • 6
  • 2
    Slightly offtopic but please stop downvoting all these answers instantly. They are not all rubbish. – Ozone Oct 01 '20 at 16:52

2 Answers2

0

All your input components are Uncontrolled Components, therefore you don't need React's state for clearing form's fields.

Using the default behaviour of <input type="submit"/> will clean the form after button press.

See <form> element in MDN docs.

<form>
  ...
  <input type="submit" value="Subscribe!">
</form>

If you go even further, you don't need state for all your onChange listeners, you can use form's onSubmit callback which holds the state of form element (again, see docs).

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • This will still leave the DOM values and the React state values out of sync. DOM values will be empty, but the state values will still be the same as the previous values. – Nitsew Oct 01 '20 at 17:05
  • 1
    Which sync? What are you talking about? He can submit form values onSubmit. – Dennis Vash Oct 01 '20 at 17:07
  • https://jsfiddle.net/9fpavrzj/ fill out this form, tap submit, and then keep tapping submit without changing the form. That is what I mean. The form is blank, but the state has the old form values. – Nitsew Oct 01 '20 at 17:27
  • Its an example of controlled form, not what I mentioned :/ – Dennis Vash Oct 01 '20 at 17:33
  • It's not a controlled form. The input fields are not using the component state to determine the input value. My example fiddle uses uncontrolled input components. – Nitsew Oct 01 '20 at 17:35
  • "but the state has the old form values", if you read my answer, I said **don't use state** you have built in form behaviour for that. On submit check the fields values using **refs** and not using the state used with `onChange`. – Dennis Vash Oct 01 '20 at 17:37
  • You have such example in React docs, just check the link in my answer. – Dennis Vash Oct 01 '20 at 17:39
  • I didn’t see your edit before responding. I would argue this is a bad use case for refs. – Nitsew Oct 01 '20 at 17:44
  • I never used controlled form or listened for changes only (like your example), so I would argue this is the best use case – Dennis Vash Oct 01 '20 at 17:45
  • That’s okay, there aren’t any hard fast rules. But the documentation clearly outlines to use refs sparingly. – Nitsew Oct 01 '20 at 17:46
  • I would be curious to see how you handle dynamic forms with refs. – Nitsew Oct 01 '20 at 17:47
  • I downvoted because it’s encouraging an anti pattern per Reacts official documentation. – Nitsew Oct 01 '20 at 17:48
  • Btw you can check popular form components like useHookForm, MUI, Antd APIs to validate my answer. – Dennis Vash Oct 01 '20 at 17:57
  • The easiest one is check how useHookForm handles onSubmit. – Dennis Vash Oct 01 '20 at 18:01
  • I checked useHookForm and their scenario falls in line with when it’s appropriate to use a ref. The library supports onFocus and onBlur, which is a circumstance in which a ref is recommended: https://reactjs.org/docs/refs-and-the-dom.html#when-to-use-refs – Nitsew Oct 01 '20 at 18:08
  • I think Ill edit the React docs to cover "should used in forms", because of "Avoid using refs for anything that can be done declaratively" you clearly believe its an anti pattern for no reason -_- – Dennis Vash Oct 01 '20 at 18:10
  • I mis understood your comment, my last comment is not correct. I’m on mobile so I can’t tell. Regardless, I still stand by my statement that using refs in OP’s example are inappropriate. – Nitsew Oct 01 '20 at 18:10
  • This is a lengthy explanation of the opinion I align with: https://stackoverflow.com/a/40568704/2909095 – Nitsew Oct 01 '20 at 18:15
-2

After your API responds successfully you can update your state like so:

const addNurse = () => {
  axios
    .post(url.concat('/api/Nxxxx/'), {
      NurseId: parseInt(nurseId),
      FirstName: firstName,
      LastName: lastName,
      Nic: nic,
      Password: password,
    })
    .then((res) => {
      alert('Saved Successfully');
      setNurseId('');
      setFirstName('');
      setLastName('');
      setNic('');
      setPassword('');
    })
    .catch((err) => {
      console.log(err);
    });
};

I would recommend you put this in a method named resetForm or similar and call that:

const resetForm = () => {
  setNurseId('');
  setFirstName('');
  setLastName('');
  setNic('');
  setPassword('');
}

const addNurse = () => {
  axios
    .post(url.concat('/api/Nxxxx/'), {
      NurseId: parseInt(nurseId),
      FirstName: firstName,
      LastName: lastName,
      Nic: nic,
      Password: password,
    })
    .then((res) => {
      alert('Saved Successfully');
      resetForm();
    })
    .catch((err) => {
      console.log(err);
    });
};

Edit

Your current implementation uses uncontrolled components. You should update all of your input fields to rely on the state value to populate the form values. The above code will not work without this and is an anti-pattern.

<input
  type="text"
  className="form-control"
  value={nurseId}
  onChange={(e) => setNurseId(e.target.value)}
></input>

Edit 2 - Full implementation example

import React, { useState } from 'react';
import axios from 'axios';

function NurseAddForm() {
    const url = process.env.REACT_APP_BACKEND_API;

    const [nurseId, setNurseId] = useState(null);
    const [firstName, setFirstName] = useState(null);
    const [lastName, setLastName] = useState(null);
    const [nic, setNic] = useState(null);
    const [password, setPassword] = useState(null);

    const handleSaveChanges = () => {
        if (
            nurseId == null ||
            nurseId === '' ||
            firstName == null ||
            firstName === '' ||
            lastName == null ||
            lastName === '' ||
            nic == null ||
            nic === '' ||
            password == null ||
            password === ''
        ) {
            alert('Error! All the filds should be filled');
        }else if (nic.length !== 10) {
            alert('NIC should be 10  Numbers with V');
        } else if (password.length < 6) {
            alert('Your password must be at least 6 characters');
        } else if (password.search(/[a-z]/) < 0) {
            alert('Your password must contain at least one lowercase letter');
        } else if (password.search(/[A-Z]/) < 0) {
            alert('Your password must contain at least one uppercase letter');
        } else if (password.search(/[0-9]/) < 0) {
            alert('Your password must contain at least one digit');
        } else if (!/^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,25}$/.test(password)) {
            alert('Your password must contain at least one special character');
        } else {
            addNurse();
        }
    };
    
    const resetForm = () => {
      setNurseId('');
      setFirstName('');
      setLastName('');
      setNic('');
      setPassword('');
    };
    
    const addNurse = () => {
        axios
            .post(url.concat('/api/Nxxxx/'), {
                NurseId: parseInt(nurseId),
                FirstName: firstName,
                LastName: lastName,
                Nic: nic,
                Password: password,
            })
            .then((res) => {
                alert('Saved Successfully');
                resetForm();
                console.log(res);
                console.log(res.data);
            })
            .catch((err) => {
                console.log(err);
            });
    };

    return (
        <div className="container">
             <button>
                <a href="/admin/nurse/view">View</a>
            </button>
            <form>
                <div className="form-group">
                    <label>Nurse ID</label>
                    <input
                        type="text"
                        className="form-control"
                        value={nurseId}
                        onChange={(e) => setNurseId(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>First Name</label>
                    <input
                        type="text"
                        className="form-control"
                        value={firstName}
                        onChange={(e) => setFirstName(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>Last Name</label>
                    <input
                        type="text"
                        className="form-control"
                        value={lastName}
                        onChange={(e) => setLastName(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>NIC</label>
                    <input
                        type="text"
                        className="form-control"
                        value={nic}
                        onChange={(e) => setNic(e.target.value)}
                    ></input>
                </div>
                <div className="form-group">
                    <label>Passowrd</label>
                    <input
                        type="password"
                        className="form-control"
                        value={password}
                        onChange={(e) => setPassword(e.target.value)}
                    ></input>
                </div>
            </form>
            <button className="btn btn-success" onClick={handleSaveChanges}>
                Save Changes
            </button>
        </div>
    );
}

export default NurseAddForm;
Nitsew
  • 3,612
  • 1
  • 15
  • 20
  • OP asked for an easy way to clear input fields, your suggestion focuses on state and that's cool, but his fields have an onChange() listener updating state on clear. edit: ah I see you've added an edit :) – Ozone Oct 01 '20 at 16:49
  • @Ozone Correct, the issue is those input values have two sources of truth now. If you reset these values without updating the state, your state will have stale data. Imagine you filled the form out with `nurseId: 1`, you submit the form, and then reset the values using your approach. The state will still have `nurseId: 1`. You fill out the form but forget to type a new `nurseId`. The form validatations will still evaluate the form as being valid, and submit to the backend a second record with `nurseId: 1`. – Nitsew Oct 01 '20 at 16:59