在 react-hook-form 的 useFieldArray 上异步调用 reset 时,reset 无法正常工作

Posted

技术标签:

【中文标题】在 react-hook-form 的 useFieldArray 上异步调用 reset 时,reset 无法正常工作【英文标题】:When reset is called asynchronously on react-hook-form's useFieldArray, reset doesn't work correctly 【发布时间】:2022-01-16 14:22:00 【问题描述】:

我正在使用 react-hook-form 和 react-navigation。在我的用例中,我使用useFieldArray 来控制不断增长的输入数组,并且当用户按下HeaderBackButton 时我想reset 表单。但是,当我将reset 传递给HeaderBackButtononPress 属性并按下按钮时,只要字段数组有任何更改,都会出现Cannot read properties of undefined (reading 'id') 的react-hook-form 错误。 在下面的代码框中,您可以附加一个项目,然后单击Reset 并重置表单。但是在附加项目后单击Back 会产生错误。这个问题只出现在 react-hook-form

代码沙盒:https://codesandbox.io/embed/react-hook-form-reset-usefieldarray-forked-yk7g4?fontsize=14&hidenavigation=1&theme=dark

import React from "react";
import  useForm, useFieldArray, Controller  from "react-hook-form";
import ReactDOM from "react-dom";
import  HeaderBackButton  from '@react-navigation/stack';

import "./styles.css";

let renderCount = 0;

function App() 
  const  control, handleSubmit, reset  = useForm(
    defaultValues: 
      loadState: "unloaded",
      names: []
    
  );
  const  fields, append  = useFieldArray(
    control,
    name: "names"
  );

  renderCount++;

  return (
    <form>
      <h1>Field Array </h1>
      <p>1. Append using the append button. </p>
      <p>2a. reset button works as expected</p>
      <p>2b. Back button, which is a HeaderBackButton errors out when there is any change to the field array</p>
      <span className="counter">Render Count: renderCount</span>
      <HeaderBackButton tintColor='#FFFFFF' 
        labelVisible=true
        onPress=()=>reset()
      />
      <button type='button' onClick=()=>reset()>reset</button>
      <button type='button' onClick=()=>append('')>append</button>
      <ul>
        fields.map((item, index) => (
            <Controller
              key=item.id
              render=( field ) => <input ...field />
              name=`names[$index]`
              control=control
              defaultValue=item.lastName
            />
        ))
      </ul>
    </form>
  );


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

【问题讨论】:

看来作者已经为此提交了一个错误修复。发布后我会更新此线程并且我已经尝试了新版本。 【参考方案1】:

验证 react-hook-form 7.22.0 解决了这个问题。

但 7.22.0 中的修复仅使字段数组 undefined 中的所有元素。它没有清除字段数组,这仍然会导致我的具体情况出现问题。

作者发现问题的症结在于异步调用reset。更新后的sandbox 表明该库的7.22.2 完全解决了该问题。

此代码在 react-hook-form 7.22.2 中按预期工作

import React from "react";
import  useForm, useFieldArray, Controller  from "react-hook-form";
import ReactDOM from "react-dom";
import  HeaderBackButton  from "@react-navigation/stack";

import "./styles.css";

let renderCount = 0;

function App() 
  const  getValues, control, reset  = useForm(
    defaultValues: 
      loadState: "unloaded",
      names: []
    
  );
  const  fields, append  = useFieldArray(
    control,
    name: "names"
  );

  renderCount++;

  console.log(getValues());
  return (
    <form>
      <h1>Field Array </h1>
      <p>1. Append using the append button. </p>
      <p>2a. reset button works as expected</p>
      <p>
        2b. Back button, which is a HeaderBackButton does clear out the
        field array now
      </p>
      <span className="counter">Render Count: renderCount</span>
      <HeaderBackButton
        tintColor="#FFFFFF"
        labelVisible=true
        onPress=() => reset( names: [] )
      />
      <button type="button" onClick=() => reset( names: [] )>
        reset
      </button>
      <button type="button" onClick=() => append( name: "abc" )>
        append
      </button>
      <ul>
        fields.map((item, index) => (
          <Controller
            key=item.id
            render=( field ) => <input value=field.value />
            name=`names.$index.name`
            control=control
          />
        ))
      </ul>
    </form>
  );


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

【讨论】:

以上是关于在 react-hook-form 的 useFieldArray 上异步调用 reset 时,reset 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

react-hook-form使用

如果输入在材料 ui 对话框中,react-hook-form 的 setValue 方法不起作用

react-hook-form 中的寄存器是啥类型?

在 react-hook-form 的 useFieldArray 上异步调用 reset 时,reset 无法正常工作

在 react-hook-form 中设置 DatePicker 的值(来自 antd)

react-hook-form 在组件中使用以传递动态文本字段的道具