【问题标题】:clear controlled components in a form using react after clicking submit button单击提交按钮后使用反应清除表单中的受控组件
【发布时间】:2020-10-13 22:08:23
【问题描述】:

我创建了一个表单来输入姓名、电子邮件、网站和消息。使用提交按钮输入详细信息后,我想重置所有字段。我不知道如何使用控制组件。请帮忙.. 这就是我输入输入字段的方式。

export default ({
noLabels = false,
margin = "",
small = false,
blueButton = false,
buttonLabel = null,
quickContact = false,
subject = "New message from website",
}) => {
 const [name, setName] = useState(
process.env.NODE_ENV === "development" ? "abc" : ""
)
const [email, setEmail] = useState(
process.env.NODE_ENV === "development" ? "abc@blabla.io" : ""
)
const [phone, setPhone] = useState(
  process.env.NODE_ENV === "development" ? "Phone" : ""
)
const [country, setCountry] = useState(
  process.env.NODE_ENV === "development" ? "Country" : ""
)
const [message, setMessage] = useState(
 process.env.NODE_ENV === "development" ? "Message" : ""
)
const [website, setWebsite] = useState(
  process.env.NODE_ENV === "development" ? "abc.io" : ""
)

const handleSubmit = e => {
  e.preventDefault()

var formData = new FormData()
formData.set("name", name)
formData.set("email", email)
formData.set("phone", phone)
formData.set("country", country)
formData.set("message", message)
formData.set("website", website)
formData.set("subject", subject)

api
  .contact(formData)
  .then(res => {
    if (typeof window !== "undefined") {
      const uikit = require("uikit")
      uikit
        .toggle(
          document.getElementById(
            quickContact
              ? "form_success_message_quick"
              : "form_success_message"
          )
        )
        .toggle()
    }
  })
  .catch(error => {
    if (typeof window !== "undefined") {
      const uikit = require("uikit")
      uikit
        .toggle(
          document.getElementById(
            quickContact ? "form_error_message_quick" : 
                    "form_error_message"
          )
        )
        .toggle()
    }
  })
 }

 return (
  <form
  action="/send-mail.php"
  className="uk-form contact_form"
  method="post"
  onSubmit={handleSubmit}
   >
     <div
       className="uk-alert-primary contact-form-success-quick"
     data-uk-alert
     id={
       quickContact ? "form_success_message_quick" : 
              "form_success_message"
    }
    hidden
     >
      <a className="uk-alert-close" data-uk-close></a>
      <p>
        Thank you for contacting us. We will get in touch with you 
         shortly.
    </p>
  </div>

     <div
    className="uk-alert-primary contact-form-error-quick"
    data-uk-alert
    id={quickContact ? "form_error_message_quick" : "form_error_message"}
    hidden>
    <a className="uk-alert-close" data-uk-close></a>
    <p>
      Thank you for contacting us. We will get in touch with you shortly.
    </p>
    </div>
    <div
    className={`uk-grid ${
      small || quickContact ? "uk-grid-small" : "uk-grid-medium"
    }`}
    >
      <div className={quickContact ? "uk-width-1-3@s" : "uk-width-1-2@s"}>
      <InputField
        label="Name *"
        value={name}
        setValue={setName}
        noLabels={noLabels}
        margin={margin}
        small={small}
      />
    </div>

    <div className={quickContact ? "uk-width-1-3@s" : "uk-width-1-2@s"}>
      <InputField
        label="Email *"
        value={email}
        setValue={setEmail}
        noLabels={noLabels}
        margin={margin}
        small={small}
      />
    </div>

    {quickContact && (
      <div className="uk-width-1-3@s">
        <InputField
          label="Website"
          value={website}
          setValue={setWebsite}
          noLabels={noLabels}
          margin={margin}
          small={small}
        />
      </div>
    )}

    {!quickContact && (
      <div className="uk-width-1-2@s">
        <InputField
          label="Phone number *"
          value={phone}
          setValue={setPhone}
          noLabels={noLabels}
          margin={margin}
          small={small}
        />
      </div>
    )}

    {!quickContact && (
      <div className="uk-width-1-2@s">
        <InputField
          label="Website"
          value={website}
          setValue={setWebsite}
          noLabels={noLabels}
          margin={margin}
          small={small}
        />
      </div>
    )}

    <div className="uk-width-1-1">
      <InputField
        label="Message *"
        value={message}
        setValue={setMessage}
        textArea
        noLabels={noLabels}
        margin={margin}
        small={small}
      />
    </div>

    <div className="uk-width-1-1 uk-text-center">
      <button
        type="submit"
        className={`uk-button ${blueButton ? "blue" : "purple"}`}
        value="Submit"
        name="submit"
      >
        {buttonLabel ? buttonLabel : "Submit"}
      </button>
    </div>
  </div>
</form>
)
  }

const InputField = ({
noLabels,
value,
setValue,
label,
 textArea = false,
 margin,
 small,
  }) => {
  <>
  {textArea ? (
    <textarea
      placeholder={label}
      className={`uk-textarea custom-margin-${
        margin ? margin + "-" : ""
      }bottom ${!small && "uk-form-large"}`}
      cols="30"
      rows="6"
      required
      value={value}
      onChange={e => setValue(e.target.value)}
    ></textarea>
    ) : (
    <input
      type="text"
      className={`uk-input custom-margin-${
        margin ? margin + "-" : ""
      }bottom ${!small && "uk-form-large"}`}
      placeholder={label}
      required
      value={value}
      onChange={e => setValue(e.target.value)}
    />
   )}
 </>     

如果可能,我想使用“e.target.reset()”重置此代码。 此外,如何使用“setValue”的方法也会很有帮助。

【问题讨论】:

  • 您是否尝试过使用“初始”状态值调用“setState”/“状态更新函数”?
  • @DrewReese 不,请你再多一点。
  • 提交处理程序中的 setValue('') 之类的东西。如果您可以提供更完整的组件示例,我可能会制定解决方案。
  • @DrewReese 哦,是的,我会.. 请在问题中再次检查我的代码。非常感谢
  • @DrewReese 请帮帮忙..我现在真的需要帮助才能完成这个..我只需要在点击提交后使用此代码重置输入

标签: reactjs forms gatsby reset submit-button


【解决方案1】:
  1. 使用单个 useState 挂钩来保存表单的值,以便更轻松地在一次调用中设置所有值。
  2. 不要直接操作 DOM,而是使用 state + React 在给定当前状态的情况下声明所需的输出。
  3. 将解决同一问题的多个条件句重构为一个条件句(回复:process.env.NODE_ENV
  4. 将回调传递给状态设置器以修改现有道具,而不必显式编写函数来手动修改每个输入的值。
const devValues = {
  name: "abc",
  email: "abc@blabla.io",
  phone: "Phone",
  country: "Country",
  message: "Message",
  website: "abc.io",
}

const defaultValues = {
  name: "",
  email: "",
  phone: "",
  country: "",
  message: "",
  website: "",
}

export default ({
  noLabels = false,
  margin = "",
  small = false,
  blueButton = false,
  buttonLabel = null,
  quickContact = false,
  subject = "New message from website",
}) => {
  const [message, setMessage] = useState(null)
  const [inputValues, setInputValues] = useState(
    process.env.NODE_ENV === "development" ? devValues : defaultValues
  )

  const handleSubmit = (e) => {
    e.preventDefault()

    var formData = new FormData()
    Object.entries(inputValues).forEach(([key, value]) => {
      formData.set(key, value)
    })

    api
      .contact(formData)
      .then((res) => {
        setMessage(
          quickContact ? "form_success_message_quick" : "form_success_message"
        )

        // clear the input values here
        setInputValues(defaultValues)
      })
      .catch((error) => {
        setMessage(
          quickContact ? "form_error_message_quick" : "form_error_message"
        )
      })
  }

  return (
    <form
      action="/send-mail.php"
      className="uk-form contact_form"
      method="post"
      onSubmit={handleSubmit}
    >
      {message && (
        <div
          className={
            message.startsWith("form_success_message")
              ? "uk-alert-primary contact-form-success-quick"
              : "uk-alert-primary contact-form-error-quick"
          }
          data-uk-alert
        >
          <a className="uk-alert-close" data-uk-close></a>
          <p>
            Thank you for contacting us. We will get in touch with you shortly.
          </p>
        </div>
      )}

      <div
        className={`uk-grid ${
          small || quickContact ? "uk-grid-small" : "uk-grid-medium"
        }`}
      >
        <div className={quickContact ? "uk-width-1-3@s" : "uk-width-1-2@s"}>
          <InputField
            label="Name *"
            name="name"
            value={inputValues.name}
            setValue={setInputValues}
            noLabels={noLabels}
            margin={margin}
            small={small}
          />
        </div>

        <div className={quickContact ? "uk-width-1-3@s" : "uk-width-1-2@s"}>
          <InputField
            label="Email *"
            name="email"
            value={inputValues.email}
            setValue={setInputValues}
            noLabels={noLabels}
            margin={margin}
            small={small}
          />
        </div>

        {quickContact && (
          <div className="uk-width-1-3@s">
            <InputField
              label="Website"
              name="website"
              value={inputValues.website}
              setValue={setInputValues}
              noLabels={noLabels}
              margin={margin}
              small={small}
            />
          </div>
        )}

        {!quickContact && (
          <div className="uk-width-1-2@s">
            <InputField
              label="Phone number *"
              name="phone"
              value={inputValues.phone}
              setValue={setInputValues}
              noLabels={noLabels}
              margin={margin}
              small={small}
            />
          </div>
        )}

        {!quickContact && (
          <div className="uk-width-1-2@s">
            <InputField
              label="Website"
              name="website"
              value={inputValues.website}
              setValue={setInputValues}
              noLabels={noLabels}
              margin={margin}
              small={small}
            />
          </div>
        )}

        <div className="uk-width-1-1">
          <InputField
            label="Message *"
            name="message"
            value={inputValues.message}
            setValue={setInputValues}
            textArea
            noLabels={noLabels}
            margin={margin}
            small={small}
          />
        </div>

        <div className="uk-width-1-1 uk-text-center">
          <button
            type="submit"
            className={`uk-button ${blueButton ? "blue" : "purple"}`}
            value="Submit"
            name="submit"
          >
            {buttonLabel ? buttonLabel : "Submit"}
          </button>
        </div>
      </div>
    </form>
  )
}

const InputField = ({
  name,
  value,
  setValue,
  label,
  textArea = false,
  margin,
  small,
}) => {
  const onChange = (e) => {
    const value = e.target.value
    setValue((prev) => ({ ...prev, [name]: value }))
  }

  return textArea ? (
    <textarea
      placeholder={label}
      className={`uk-textarea custom-margin-${
        margin ? margin + "-" : ""
      }bottom ${!small && "uk-form-large"}`}
      cols="30"
      rows="6"
      required
      value={value}
      onChange={onChange}
    />
  ) : (
    <input
      type="text"
      className={`uk-input custom-margin-${margin ? margin + "-" : ""}bottom ${
        !small && "uk-form-large"
      }`}
      placeholder={label}
      required
      value={value}
      onChange={onChange}
    />
  )
}

【讨论】:

  • 这部分代码中的“setInputValues({})”如何设置值?你能解释一下吗?
  • api .contact(formData) .then((res) => { setMessage( quickContact ? "form_success_message_quick" : "form_success_message" ) // 清除这里的输入值 setInputValues({}) }) . catch((error) => { setMessage( quickContact ? "form_error_message_quick" : "form_error_message" ) })
  • 这是一个从useState返回的setter函数。如果你不熟悉它,check the documentation here。我提供的代码不是设置对象上的每个属性,而是简单地将其重置为具有相同效果的“空”对象,尽管您可能希望将其替换为具有空字符串的静态对象以避免 React 抱怨转换从非托管组件到托管组件。
  • 但是我从这段代码中得到了这个错误。我已将其添加到您的答案中。请检查是否可以。
  • @Perera 抱歉——这是由于 SyntheticEvent 在回调运行时被 React “回收”。我已经更新了 onChange 处理程序来解决它。
【解决方案2】:

在正确答案,尤其是@coreyward 的建议中,我想添加另一种方法,可以帮助您或其他遇到同样麻烦的用户。

您还可以使用useRef hookref 到您的form 标记,然后使用本机reset() 函数将其清除:

    export default ({
      noLabels = false,
      margin = "",
      small = false,
      blueButton = false,
      buttonLabel = null,
      quickContact = false,
      subject = "New message from website",
    }) => {
      const mailForm = useRef(null)
      //... more code
    }
  return (
    <form
      action="/send-mail.php"
      className="uk-form contact_form"
      method="post"
      onSubmit={handleSubmit}
      ref={mailForm}
    >
  )

然后,在您的提交功能中,您将mailForm.current 作为您的表单。你可以简单地:

const handleSubmit = (e) => {
    e.preventDefault()

    var formData = new FormData()
    Object.entries(inputValues).forEach(([key, value]) => {
      formData.set(key, value)
    })

    api
      .contact(formData)
      .then((res) => {
        setMessage(
          quickContact ? "form_success_message_quick" : "form_success_message"
        )

        // clear the input values here
        mailForm.curent.reset();
      })
      .catch((error) => {
        setMessage(
          quickContact ? "form_error_message_quick" : "form_error_message"
        )
      })
  }

【讨论】:

  • 在托管更新流程之外重置受控组件的状态会导致新状态在后续渲染中被覆盖。
  • @Ferran 我们可以将 rest() 用于受控组件吗?抱歉,我对反应编码不太熟悉,这就是为什么要问..
  • @Perera 当然可以,只是需要考虑到,如果您在这些字段上有状态,则可能会导致重新渲染问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 1970-01-01
  • 2022-07-05
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多