jvs789789
jvs789789

Reputation: 203

React - clearing email input field, after form submission

After the form is submitted, the password field input is emptied, but not the email input field.

As you can see in the HandleSubmit function: ref.current.value = ""; is what I've used as an attempt to clear the input fields after form submission, but it is only working for the password input field.

I've looked at a few other answers on SO, and I've tried e.target.reset(), and I've also tried setField(""); with no luck yet yet.


import React from 'react';
import Form from 'react-bootstrap/Form';
import { Button } from 'react-bootstrap';
import { Container } from 'react-bootstrap';
import { useState } from 'react';
import { useRef } from 'react';

const allThis = () => {
  const [form, setForm] = useState({})
  const [errors, setErrors] = useState({})

  const setField = (field, value) => {
    setForm({
      ...form,
      [field]: value
    })
    // Check and see if errors exist, and remove them from the error object:
    if (!!errors[field]) setErrors({
      ...errors,
      [field]: null
    })
  }

  const ref = useRef(null); // set up empty field

  const handleSubmit = (e) => {
    e.preventDefault();
    const newErrors = findFormErrors()
    if (Object.keys(newErrors).length > 0) {
      setErrors(newErrors)
    } else {
      alert('Thank you for your feedback!');
      ref.current.value = ""; // empty the field
    }
  }

  const findFormErrors = () => {
    const { email, password } = form
    const newErrors = {};
    if (!email || email === '') newErrors.email = 'cannot be blank!';
    /* else if (email.length > 30) newErrors.email = 'email is too long!'; */
    if (!password || password === " ") newErrors.password = "cannot be blank";
    return newErrors
  }

  return (
    <Container>
      <Form className="reduceForm">
        <Form.Label className="contact">Contact Me</Form.Label>
        <Form.Group className="mb-3" controlId="formBasicEmail">
          <Form.Label>Email address</Form.Label>
          <Form.Control input ref={ref} type="email" placeholder="Enter email"  
            onChange={e => setField('email', e.target.value)}
            isInvalid={!!errors.email} />
          <Form.Control.Feedback type='invalid'>
            {errors.email}
          </Form.Control.Feedback>
        </Form.Group>

        <Form.Group className="mb-3" controlId="formBasicPassword">
          <Form.Label>Password</Form.Label>
          <Form.Control input ref={ref} type="password" placeholder="Password"
            onChange={e => setField('password', e.target.value)}
            isInvalid={!!errors.password} />
          <Form.Control.Feedback type='invalid'>
            {errors.password}
          </Form.Control.Feedback>
        </Form.Group>
        <Button onClick={handleSubmit} variant="primary" type="submit">
          Submit
        </Button>
      </Form>
    </Container>
  )

}

export default allThis

Upvotes: 2

Views: 491

Answers (3)

Nicky McCurdy
Nicky McCurdy

Reputation: 19554

The React team recommends writing forms declaratively, using state instead of refs. You're already setting your inputs to state when they're changed, so you can solve this in an easier to maintain way by passing value props to your inputs.

import React from 'react';
import Form from 'react-bootstrap/Form';
import { Button } from 'react-bootstrap';
import { Container } from 'react-bootstrap';
import { useState } from 'react';

const initialForm = {
  email: '',
  password: ''
};

export default function AllThis() {
  const [form, setForm] = useState(initialForm);
  const [errors, setErrors] = useState({});

  const setField = (field, value) => {
    setForm({
      ...form,
      [field]: value
    });
    // Check and see if errors exist, and remove them from the error object:
    if (!!errors[field])
      setErrors({
        ...errors,
        [field]: null
      });
  };

  const handleSubmit = e => {
    e.preventDefault();
    const newErrors = findFormErrors();
    if (Object.keys(newErrors).length > 0) {
      setErrors(newErrors);
    } else {
      alert('Thank you for your feedback!');
      setForm(initialForm);
    }
  };

  const findFormErrors = () => {
    const { email, password } = form;
    const newErrors = {};
    if (!email || email === '') newErrors.email = 'cannot be blank!';
    /* else if (email.length > 30) newErrors.email = 'email is too long!'; */
    if (!password || password === ' ') newErrors.password = 'cannot be blank';
    return newErrors;
  };

  return (
    <Container>
      <Form className="reduceForm">
        <Form.Label className="contact">Contact Me</Form.Label>
        <Form.Group className="mb-3" controlId="formBasicEmail">
          <Form.Label>Email address</Form.Label>
          <Form.Control
            input
            type="email"
            placeholder="Enter email"
            value={form.email}
            onChange={e => setField('email', e.target.value)}
            isInvalid={!!errors.email}
          />
          <Form.Control.Feedback type="invalid">
            {errors.email}
          </Form.Control.Feedback>
        </Form.Group>

        <Form.Group className="mb-3" controlId="formBasicPassword">
          <Form.Label>Password</Form.Label>
          <Form.Control
            input
            type="password"
            placeholder="Password"
            value={form.password}
            onChange={e => setField('password', e.target.value)}
            isInvalid={!!errors.password}
          />
          <Form.Control.Feedback type="invalid">
            {errors.password}
          </Form.Control.Feedback>
        </Form.Group>
        <Button onClick={handleSubmit} variant="primary" type="submit">
          Submit
        </Button>
      </Form>
    </Container>
  );
}

https://codesandbox.io/s/react-clearing-email-input-field-after-form-submission-o41dki?file=/src/AllThis.js

Upvotes: 1

Zainal Abidin
Zainal Abidin

Reputation: 79

You have to declare different variable for email and password. I prefer just using useState.

const [email, setEmail] = useState("");
const [password, setPassword] = useState("")

// Input
<Form.Control input value={email} type="email" placeholder="Enter email"  
        onChange={e => setEmail(e.target.value}
        isInvalid={!!errors.email} />
<Form.Control input value={password} type="password" placeholder="Password"  
        onChange={e => setPassword(e.target.value}
        isInvalid={!!errors.password} />

// handleSubmit
setEmail("");
setPassword("");

Upvotes: 1

Akash Sinha
Akash Sinha

Reputation: 309

you are setting one ref to two different fields. Therefore only the last one is being retained i.e. password one (and email field's ref is being overwritten) use 2 different refs for them. Of if possible use ref to your form if react-bootstrap/form supports it.

Upvotes: 1

Related Questions