不使用库在 React 中使用表单

2025-06-07

不使用库在 React 中使用表单

在 JavaScript 中处理表单可能是一项艰巨的任务,在本文中我们将学习如何处理它们。

不受控制的输入

首先我们需要讨论一下非受控输入,这里我说的输入,其实也包括 select 或 textarea。这是输入的默认状态,在这种情况下,我们不做任何特殊处理,让浏览器自行处理它的值。

function Form() {
  const [message, setMessage] = React.useState("");

  function handleSubmit(event) {
    event.preventDefault();
    setMessage(event.target.elements.message.value);
    event.target.reset();
  }

  return (
    <>
      <p>{message}</p>
      <form onSubmit={handleSubmit}>
        <input name="message" type="text" />
      </form>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

正如我们在上面的例子中看到的,message在用户提交表单后,我们使用输入的值来更新我们的状态,按下enter,并重置输入值,我们只需使用reset()表单的方法重置整个表单。

这是正常的 DOM 操作,用于读取值并重置它,对 React 来说没有什么特别的。

受控输入

现在让我们来谈谈有趣的部分,控制器输入/选择/文本区域是一个值绑定到状态的元素,我们需要更新状态来更新用户看到的输入值。

function Form() {
  const [message, setMessage] = React.useState("");

  function handleSubmit(event) {
    event.preventDefault();
    setMessage("");
  }

  function handleChange(event) {
    setMessage(event.target.value);
  }

  return (
    <>
      <p>{message}</p>
      <form onSubmit={handleSubmit}>
        <input
          name="message"
          type="text"
          onChange={handleChange}
          value={message}
        />
      </form>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

我们的示例将input值设置为message并附加一个onChange我们称之为的事件监听器handleChange,在这个函数内部我们需要event.target.value接收输入的新值,即当前值加上用户输入的值,我们调用它setMessage来更新我们的组件状态,这将更新标签的内容p和标签的值input以匹配新状态。

如果我们想要重置输入,我们可以调用setMessage(""),就像在中所做的那样handleSubmit,这将重置状态并重置输入的值和p内容。

添加简单验证

_现在让我们添加一个简单的验证,复杂的验证类似但有更多的规则,在这种情况下,如果使用特殊字符,我们将使输入无效。

function Form() {
  const [message, setMessage] = React.useState("");
  const [error, setError] = React.useState(null);

  function handleSubmit(event) {
    event.preventDefault();
    setError(null);
    setMessage("");
  }

  function handleChange(event) {
    const value = event.target.value;
    if (value.includes("_")) setError("You cannot use an underscore");
    else setError(null);
    setMessage(value);
  }

  return (
    <>
      <p>{message}</p>
      <form onSubmit={handleSubmit}>
        <input
          id="message"
          name="message"
          type="text"
          onChange={handleChange}
          value={message}
        />
        {error && (
          <label style={{ color: "red" }} htmlFor="message">
            {error}
          </label>
        )}
      </form>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

我们创建两个状态,一个用于输入值,另一个用于错误信息。和之前一样,handleSubmit我们将message状态重置为空字符串,另外,我们将error状态重置为null

在 中,handleChange我们将读取输入的新值并检查是否存在下划线。如果发现下划线,我们将错误状态更新为消息;"You cannot use an underscore"如果不存在,我们将错误状态设置为null。验证完成后,我们将message使用新值更新状态。

在返回的 UI 中,我们将检查是否存在,error并渲染一个label指向输入框的红色文本,并在其中显示错误消息。错误信息位于标签内,以便用户点击它并将焦点移至输入框。

控制文本区域

之前我说过使用inputtextarea是相似的,事实上也是如此,让我们将渲染的元素更改为textarea,上面的代码将继续工作而无需任何其他更改,如下所示。

function Form() {
  const [message, setMessage] = React.useState("");
  const [error, setError] = React.useState(null);

  function handleSubmit(event) {
    event.preventDefault();
  }

  function handleChange(event) {
    const value = event.target.value;
    if (value.includes("_")) {
      setError("You cannot use an underscore");
    } else {
      setError(null);
      setMessage(value);
    }
  }

  return (
    <>
      <p>{message}</p>
      <form onSubmit={handleSubmit}>
        <textarea
          id="message"
          name="message"
          onChange={handleChange}
          value={message}
        />
        {error && (
          <label style={{ color: "red" }} htmlFor="message">
            {error}
          </label>
        )}
      </form>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

虽然通常textarea是一个具有内部内容的元素,就像<textarea>Content here</textarea>在 React 中一样,为了改变值,我们使用value像输入和onChange事件一样的 prop,使输入和文本区域之间的变化相似。

控制选择

现在我们来谈谈select。与 一样,textarea你将其视为普通的input,传递一个value带有选定值的 prop ,并使用 监听值的变化onChange。传递给 的值select应该与其中一个选项的值匹配,以将其中一个选项显示为当前选定的选项。

function Form() {
  const [option, setOption] = React.useState(null);
  const [error, setError] = React.useState(null);

  function handleSubmit(event) {
    event.preventDefault();
  }

  function handleChange(event) {
    setOption(event.target.value);
  }

  function handleResetClick() {
    setOption(null);
  }

  function handleHooksClick() {
    setOption("hooks");
  }

  return (
    <>
      <p>{option}</p>
      <form onSubmit={handleSubmit}>
        <select onChange={handleChange} value={option}>
          <option value="classes">Classes</option>
          <option value="flux">Flux</option>
          <option value="redux">Redux</option>
          <option value="hooks">Hooks</option>
        </select>
      </form>
      <button type="button" onClick={handleResetClick}>
        Reset
      </button>
      <button type="button" onClick={handleHooksClick}>
        Hooks!
      </button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

使用文件输入

最后,我们来谈谈文件输入框。这个特殊的输入框无法控制,但仍然可以获取一些数据并将其保存在状态中,以便在其他地方显示。在下面的示例中,我们为隐藏的文件输入框创建了一个自定义 UI。

function Form() {
  const [fileKey, setFileKey] = React.useState(Date.now());
  const [fileName, setFileName] = React.useState("");
  const [fileSize, setFileSize] = React.useState(0);
  const [error, setError] = React.useState(null);

  function resetFile() {
    setFileKey(Date.now());
    setFileName("");
    setFileSize(0);
    setError(null);
  }

  function handleChange(event) {
    const file = event.target.files[0];

    setFileSize(file.size);

    if (file.size > 100000) setError("That file is too big!");
    else setError(null);

    setFileName(file.name);
  }

  return (
    <form>
      <label htmlFor="file">
        Select a single file to upload. (max size: 100kb)
        <br />
        {fileName && (
          <>
            <strong>File:</strong> {fileName} ({fileSize / 1000}kb)
          </>
        )}
        <input id="file" type="file" key={fileKey} onChange={handleChange} style={{ display: "none" }} />
      </label>
      {error && (
        <label style={{ color: "red" }} htmlFor="file">
          {error}
        </label>
      )}
      <button type="button" onClick={resetFile}>
        Reset file
      </button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

我们监听变化事件并读取文件大小和名称并验证文件的大小,如果文件太大,我们将状态设置error为消息"That file is too big!",如果文件不是那么大,我们将错误设置为null,如果用户之前选择了一个大文件,这让我们删除之前的错误。

我们还有一个按钮来重置输入,因为我们无法控制状态,所以我们可以使用key强制 React 再次渲染输入并在过程中重置它,我们使用当前日期,每次用户单击Reset file它时都会获取当前日期并将其保存到fileKey状态并重置输入。

文章来源:https://dev.to/sergiodxa/working-with-forms-in-react-without-libraries-4iad
PREV
24 个很棒的开源 Rust 项目
NEXT
🔥业余项目想法清单