【问题标题】:React Bootstrap reset form after submit提交后 React Bootstrap 重置表单
【发布时间】:2021-09-12 09:16:37
【问题描述】:

您好,我正在尝试在 React/Next.js 应用程序中使用 React Bootstrap 设置联系表单。提交后如何重置表单?当我添加重置句柄时,验证不再起作用。

  // Form validation
  const [validated, setValidated] = useState(false);

  // Thank you Message
  const [thankYouMessage, setThankYouMessage] = useState(false);

  // Form submit handler
  async function handleSubmit(e) {
    e.preventDefault();
    e.stopPropagation();

    const formData = new FormData();

    Array.from(e.currentTarget.elements).forEach((field) => {
      if (!field.name) return;
      formData.append(field.name, field.value);
    });

    await fetch(
      "https://domain.tld/wp-json/contact-form-7/v1/contact-forms/1234/feedback",
      {
        body: formData,
        method: "POST",
      }
    )
      .then((response) => response.json())
      .then((response) => {
        if (response.status === "mail_sent") {
          setThankYouMessage(!thankYouMessage);
        } else if (response.status === "mail_failed") {
          alert("Message failed to send.");
        }
      });

    setValidated(true);
  }

这是表格:

  <div>
    <Form
      noValidate
      validated={validated}
      onSubmit={handleSubmit}
    >
      <Form.Group controlId="your-name">
        <Form.Control
          required
          type="text"
          placeholder="Your name"
          name="your-name"
        />
        <Form.Control.Feedback type="invalid">
          Please enter your name
        </Form.Control.Feedback>
      </Form.Group>
      <Form.Group controlId="your-email">
        <Form.Control
          required
          type="email"
          placeholder="Your email address"
          name="your-email"
        />
        <Form.Control.Feedback type="invalid">
          Please enter your email
        </Form.Control.Feedback>
      </Form.Group>
      <Form.Group controlId="your-message">
        <Form.Control
          as="textarea"
          cols={30}
          rows={6}
          placeholder="Write your message..."
          name="your-message"
        />
      </Form.Group>
      <Button type="submit" variant="primary" size="lg">
        Send Message
        <span></span>
      </Button>
    </Form>
    <Alert
      variant="success"
      className={thankYouMessage ? "d-block mt-3" : "d-none"}
    >
      Thank you for your message. It has been sent.
    </Alert>
  </div>

我尝试使用useRef() 设置重置句柄,但没有成功:

  const formRef = useRef(null);
  const handleReset = () => {
    formRef.current.reset();
    setValidated(false);
  };

然后在表单上添加ref={formRef}setValidated(true); 之后我做了handleReset(); 但随后验证不再起作用。 欢迎对此提出任何建议,也欢迎任何有关代码的 cmets!

这是将 ref={formRef} 添加到 Form 标签时发生的 gif 图像:

  const formRef = useRef();
  const handleReset = () => {
    formRef.current.reset();
    setValidated(false);
  };

在获取中:

      .then((response) => response.json())
      .then((response) => {
        if (response.status === "mail_sent") {
          setThankYouMessage(!thankYouMessage);
          handleReset();
        } else if (response.status === "mail_failed") {
          alert("Message failed to send.");
        }
      });

【问题讨论】:

    标签: reactjs forms next.js react-bootstrap


    【解决方案1】:

    据我了解,您想在重置之前先获得响应吗? e.preventDefault() 正在阻止表单重置,但是通过删除它,页面会立即重新加载,而无需等待响应。如果这是您面临的问题,那么有几个解决方案:

    1. 使用reload(只是重新加载当前文档)。
        .then((response) => {
                if (response.status === "mail_sent") {
                  setThankYouMessage(!thankYouMessage);
                } else if (response.status === "mail_failed") {
                  alert("Message failed to send.");
                }
                location.reload();
              });
    
    1. 使用submit(只提交表单而不发送提交事件或表单验证,但这很好,因为您之前已经验证过了)。
        const formRef = useRef(null);
    
        ...
    
        .then((response) => {
                if (response.status === "mail_sent") {
                  setThankYouMessage(!thankYouMessage);
                } else if (response.status === "mail_failed") {
                  alert("Message failed to send.");
                }
                formRef.current.submit();
              });
    
        ...
    
        <Form
          noValidate
          validated={validated}
          onSubmit={handleSubmit}
          ref={formRef}
        >    
    
    1. 使用requestSubmit(与单击提交按钮相同)。这里需要EventListener,因为本质上,您想要的是通过首先调用preventDefault 来禁用默认操作,然后在获得响应后再次启用默认操作。可惜没有enableDefault这么方便的功能。

      流程是这样的:

      1. addEventListenerpreventDefault 被调用(现在任何按钮点击不会重置表单)
      2. 填写表格并点击提交按钮
      3. 获取并收到响应
      4. removeEventListenerpreventDefault 被调用(现在任何按钮点击重置表单)
      5. 调用requestSubmit提交表单,就像单击提交按钮一样,这将重置表单
        const formRef = useRef(null);
    
        ...
    
        // useCallback is needed here instead of a normal function because
        // formRef will be updated every time onChange occurs because react renders again
        // which will cause addEventListener/removeEventListener to not work as expected 
        const stopReset = useCallback((event) => {
            event.preventDefault();
            // stopPropagation will prevent form validation but if you really need it here
            // then you need to add another event listener for handleSubmit in useEffect
            // and you can remove onSubmit={handleSubmit} in Form
            // event.stopPropagation();
        }, []);
    
        useEffect(() => {
            formRef.current.addEventListener('submit', stopReset);
            // Uncomment this only if you need stopPropagation above
            // formRef.current.addEventListener('submit', handleSubmit);
        },[]); // Add dependencies in the array, leave it blank if you don't have any
    
        async function handleSubmit(e) {
            // remove preventDefault and stopPropagation here
        
            const formData = new FormData();
        
            Array.from(e.currentTarget.elements).forEach((field) => {
              if (!field.name) return;
              formData.append(field.name, field.value);
            });
        
            await fetch(
              "https://domain.tld/wp-json/contact-form-7/v1/contact-forms/1234/feedback",
              {
                body: formData,
                method: "POST",
              }
            )
              .then((response) => response.json())
              .then((response) => {
                if (response.status === "mail_sent") {
                  setThankYouMessage(!thankYouMessage);
                } else if (response.status === "mail_failed") {
                  alert("Message failed to send.");
                }
                formRef.current.removeEventListener('submit', stopReset);
                formRef.current.requestSubmit()
              });
        
            setValidated(true);
        }
    
        ...
    
        <Form
          noValidate
          validated={validated}
          onSubmit={handleSubmit}
          ref={formRef}
        >
    

    如果您想在重置前显示您的消息一段时间,您可以添加一个计时器。

        .then(async (response) => {
                if (response.status === "mail_sent") {
                  setThankYouMessage(!thankYouMessage);
                } else if (response.status === "mail_failed") {
                  alert("Message failed to send.");
                }
                // sleep for 10 seconds
                await new Promise(r => setTimeout(r, 10000));
                // call whichever method to reset
              });
    

    【讨论】:

    • 我已经尝试了您的第一个 2 解决方案但不起作用,因为验证不再起作用。有了它,它无论如何都会发送表单而不进行验证。当我添加 const formRef = useRef(); 时,它仍然可以验证,但在提交表单时验证不会被清除。
    • @Mark 你能用计时器试试前两个吗?如果您想清除验证,则还需要致电setValidated(false);
    • 当然。另请查看我的帖子,只是添加了更多解释和 GIF,以显示添加 const formRef = useRef(); 时发生的情况
    • 当我将 setValidated(false); 添加到 fetch if (response.status === "mail_sent") 时,它仍然没有删除验证,如我帖子中的 GIF 所示。但它确实清除了表单。
    • 您可以尝试重置className 吗? formRef.current.className = ""formRef.current.classList.remove("was-validated")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2021-07-02
    相关资源
    最近更新 更多