兰兰自语 發表於 2022-2-5 22:12:00

react-hook-form 使用小结

<p>表单状态管理曾经一直是让前端头疼的问题,错误提示,校验规则,动态表单,重置。。。搞得人头大。好在近几年也出现了不少好的社区方案,比如 Formik,react-hook-form, react-final-form等等,今天我们来谈谈其中的 react-hook-form。</p>
<h3 id="useform">useForm</h3>
<p>useForm 是最基础的表单状态管理钩子,它接受以下参数:</p>
<pre><code>const {
handleSubmit,
watch
} = useForm({
defaultValues: {},
mode: 'onSubmit' // onChange | onBlur | onSubmit | onTouched | all
})
</code></pre>
<p>mode 可以控制触发校验的时机,如果我们希望用户能尽快感知到填写出错了,可以使用 'all';</p>
<p>defaultValues, 如果表单从后台拉下来数据,有初始值,可以从这里传进去。</p>
<h3 id="rules">rules</h3>
<p>rules可以用来校验值,支持以下字段:</p>
<pre><code class="language-js">{
required: true,
maxLength; // 最大长度
minLength; //最小长度
max: 5 // 最大值
min: 5 // 最小值
pattern: /1\d{12}/
validate: (v) =&gt; v &gt; 100
validate: {
        greaterThan: (v) =&gt; v &gt; 100,
        lessThan: (v) =&gt; v&lt; 200
        }
}
</code></pre>
<h3 id="使用controller-来和ui库集成">使用<code>&lt;Controller /&gt;</code>来和UI库集成</h3>
<p>使用<code>useForm</code>返回的register函数,可以很方便地使用原生html元素构建一个表单,但是大部分情况下,我们是使用UI库来开发表单的。</p>
<p><code>&lt;Controller/&gt;</code>组件接受control, name,rules和 render函数等作为属性,render函数接受field, fieldState, formState3个参数:field里面包括用来控制字段的onChange函数和value,fieldState 包含字段的校验信息。通过这些信息,我们就可以控制这个字段是应该怎么渲染;</p>
<pre><code class="language-js">    field: { onChange, onBlur, value, name, ref },
    fieldState: { invalid, isTouched, isDirty, error },
    formState,
</code></pre>
<pre><code class="language-JSX">&lt;Controller
control={control}
rules={{ required: true }}
name="test"
render={({
    field: { onChange, onBlur, value, name, ref },
    fieldState: { invalid, isTouched, isDirty, error },
    formState,
}) =&gt; (
    &lt;Checkbox
      onBlur={onBlur} // notify when input is touched
      onChange={onChange} // send value to hook form
      checked={value}
      inputRef={ref}
    /&gt;
)}
/&gt;
</code></pre>
<h3 id="watch和usewatch-构建动态表单">watch和useWatch 构建动态表单</h3>
<p>经常有这样的场景,就是一个输入,会影响接下来的表单展示。由于useForm的表单状态发生变化,虽然会被记录下来,但是并不一定会触发重新渲染。当我们需要当值发生变化的时候更新UI,就要用到<code>useWatch</code>或者<code>watch</code>;</p>
<p>假设有这么一个场景,我们需要实时回显用户的输入,那么可以这么写:</p>
<pre><code class="language-JSX">const watchedName = watch('name', '');

return &lt;div&gt;
    &lt;label&gt;Name&lt;/label&gt;
    &lt;input
      type="text"
            {...register("name", { required: true, maxLength: 50 })}
    /&gt;
    &lt;div&gt;name: {watchedName}&lt;/div&gt;
&lt;/div&gt;

</code></pre>
<p>这时,当输入框的字段更新时,就会触发重新渲染,从而回显用户输入的值。那么<code>watch</code>和<code>useWatch</code>的区别是啥呢,watch是 <code>useForm</code>钩子的返回值,<code>useWatch</code>是一个全新的钩子函数,在一些不需要父组件更新的场景下,可以获得更好的性能。下面这个例子将<code>watch</code>传入子组件,可以发现,子组件更新时父组件也更新了。</p>
<iframe src="https://codesandbox.io/embed/react-hook-form-v7-usewatch-forked-yxvtr?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden" title="react-hook-form-v7-useWatch (forked)" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>
<h3 id="trigger来手动触发校验">trigger来手动触发校验</h3>
<p>一般来说,触发发校验是当用户输入完成,失焦或者表单提交时触发的。但是有一种场景是,当后面的字段的校验依赖于前面字段的输入时,这时就要使用到<code>trigger</code>了。举个例子,我们选择省之后,要触发对省下面的市的校验:</p>
<pre><code class="language-ts">const sheng = watch("sheng");
useEffect(() =&gt; {
    if (sheng) {
      trigger("shi");
    }
}, );
</code></pre>
<iframe src="https://codesandbox.io/embed/react-hook-form-v6-triggervalidation-forked-rm58fn?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden" title="react-hook-form-v6-triggerValidation (forked)" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>
<p>通过<code>trigger</code>我们就可以在省选项发生变化时,触发对省会字段的校验,从而及时发现问题。</p>
<h3 id="usefieldarray来新增表单项">useFieldArray来新增表单项</h3>
<p>我们经常会遇到这样的场景--新增表单项,比如新增收货地址。react-hook-form为我们提供了<code>useFieldArray</code>这个hook来完成这些工作:</p>
<pre><code class="language-js">const { register, control, handleSubmit, reset, watch } = useForm({
    defaultValues: {
      test: [{ firstName: "Bill", lastName: "Luo" }]
    }
});
const {
    fields,
    append,
    prepend,
    remove,
    swap,
    move,
    insert,
    replace
} = useFieldArray({
    control,
    name: "test"
});
</code></pre>
<p>我们可以使用<code>prepend</code>在队首插入一个表单项,<code>append</code>在队尾插入一个表单项,<code>remove</code>来去掉一个表单项。当然如果我们希望实时显示表单项里的数据的时候,还是要使用<code>watch</code>和<code>useWatch</code></p>
<iframe src="https://codesandbox.io/embed/react-hook-form-usefieldarray-ssugn?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden" title="React Hook Form - useFieldArray " allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>

</div>
<div id="MySignature" role="contentinfo">
    <strong>cnblogs-md-editor编辑器</strong>,用Markdown写博客就用它<br><br>
来源:https://www.cnblogs.com/imgss/p/15848408.html
頁: [1]
查看完整版本: react-hook-form 使用小结