React杂谈#1 React-Hook-Form - 建立快速的React表单

有使用过React的同学都知道,用React做输入控制的时候, 通常做法是建立一个input的state, 具体如下:

import { useState } from "react";export default function Form() {  const [surname, setSurname] = useState("");  const [firstName, setFirstName] = useState("");  const [age, setAge] = useState(0);  const onFormSumbit = (e) => {    e.preventDefault();    console.log("Form Submitted");    const formData = new FormData(e.target);    for (const pair of formData.entries()) {      console.log(`${pair[0]}: ${pair[1]}`);    }  };  //every single rendering trigger the following code once  console.log("Form rendered");  return (    <form onSubmit={onFormSumbit}>      <h1>Using Pure React</h1>      First Name:      <input        onChange={(e) => {          setFirstName(e.target.value);        }}        name="firstName"        value={firstName || ""}      />      <br />      Surname:      <input        onChange={(e) => {          setSurname(e.target.value);        }}        name="surname"        value={surname || ""}      />      <br />      Age:      <input        onChange={(e) => {          setAge(e.target.value);        }}        name="age"        value={age || ""}        type="number"      />      <br />      <input type="submit" />    </form>  );}

事实上React的官方best practise也是这样的。 但是当製作有多个输入项的表单时, 事情就麻烦了。 不单每个输入项都要设定一个State给他, 代码变得臃肿难阅读。 更严重的是, 每次用户填写表单的时候, 即使是再微小的改动, 也会触发整个表单的渲染(rendering)。 每增加一个字, 渲染一次,每删除一个字,渲染一次, 那样前端的效率会大大受到影响。

传统React填表过程触发多次渲染

解决这类问题的办法有很多,例如我们可以使用useEffect去优化渲染时的效率,但这里有一个更好的工具去完完全全避免这因为input而产生的渲染,这就是今天要介绍的React-Hook-Form。
以下是一个使用React-Hook-Form重新製作的表单:

import { useForm } from "react-hook-form";export default function HookForm() {  const { register, handleSubmit } = useForm();  const onFormSumbit = (formObj, e) => {    e.preventDefault();    console.log("Form Submitted");    const formData = new FormData(e.target);    for (const pair of formData.entries()) {      console.log(`${pair[0]}: ${pair[1]}`);    }  };  //every single rendering trigger the following code once  console.log("Form rendered");  return (    <form onSubmit={handleSubmit(onFormSumbit)}>      <h1>Using React-Hook-Form</h1>      First Name:      <input {...register("firstName")} />      <br />      Surname:      <input {...register("surname")} />      <br />      Age:      <input {...register("age")} />      <br />      <input type="submit" />    </form>  );}

你会看到与传统表单最大的分别是已经没有了setState, 取而代之是一次useForm, 以及在input裏面的register函数。 
再来看看它在填写表单时的渲染次数

React-hook-form只触发1次渲染

什么!只有1次!?对, 这就是React-Hook-Form的神奇魔法。它为什么做到如此强大的功能呢, 关键就在于一个字:ref

<input {...register("firstName")} />

这个register函数会返回一个包含4个属性(attribute)的物件(object),那4个属性分别是name,onChange,onBlur,以及ref。这里的name会是我们传入register的第一个参数,通常是输入项的名称。onChange,onBlur 传入对应的event handler。最后的ref属性提供了一个接口,让React-Hook-Form能绕过React的Virtual Dom,访问input真实的DOM nodes。

因为React-Hook-Form 在最后提交的时候才通过ref取得DOM nodes的数值,input的数值根本没有绑定在React里。所以我们改变input的value,也不会触发渲染。

总结

对比单纯用state做的表单,React-Hook-Form提供了一个简单易用的介面,除了让setup变得更快,更解决了输入渲染的问题,在建立多个或者複杂表单时会很有用。
React-Hook-Form亦提供了诸多如数据验证等等其他表单常见的功能,十分推介大家尝试这个Library。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章