---
# System prepended metadata

title: React Hook Form - Rare bugs encountered with useFieldArray
tags: [SywxS7ADgl, self-taught, published, blog, josysnavi]

---

![image](https://hackmd.io/_uploads/SywxS7ADgl.png)

If you'are a frontend developer, you would probably agree that React Hook Form is one of the go-to libraries for form validation. It's true value shines particularly in complex forms that require dynamic operations such as adding, removing, and reordering fields. One of its strengths is its ability to accurately track changes and avoid unnecessary re-rendering. However, this very strength can also cause unexpected bugs.

In this article, I'll introduce two useFieldArray bugs that I encountered and how I solved them.

### 1. Bug#1: useFieldArray in a nested component

#### 💥 What Happened

I was building a flexible form, similar to Google Forms, where users could add questions and change the answer types.

This form had two layers of useFieldArray :

`useFieldArray #1`: Array of questions

`useFieldArray #2`: Array of answers within each question

The problem was that after adding and then deleting a question, the question or answer text could no longer be edited. The input fields would become unresponsive.

#### 🤯 My thoughts at the time

To be honest, I was confused at first, because it had almost the same structure as the nested useFieldArray example in the documentation. The only difference was that the documentation used direct input (register), while I was using a Controller.

<u>Documented example (direct binding):</u>

```javascript!
<input
 placeholder="first name"
 {...register("firstName")}
/>
```

<u>My example (using Controller):</u>

```javascript!
<Controller
 control={control}
 name="firstName"
 render={({ field, fieldState: { error } }) => (
  <input
   {...field}
   placeholder="first name"
   error={error?.message}
   />
  )}
/>
```

The actual field names were deeper and looked like this:

```javascript!
content.${questionIndex}.answers.${answerIndex}.answerText
```

#### ✅ Solution

Did you notice that we're passing `{...field}` to the `<input />` in the `Controller`? This is actually not explicitly stated in the official documentation.

This worked fine with other `useFieldArray` calls, but it didn't work in this case. I suspect that when the question was deleted in the middle, React Hook Form didn't reset the state of the nested field correctly, and the Controller didn't detect the change properly.

So what I tried was explicitly calling `register()` in the `Controller`:

```javascript!
<input
 {...register(`content.${questionIndex}.answers.${answerIndex}.answerText`)}
/>
```

It seems a bit redundant, but this ensures a re-render after any change, and solved the problem. To be honest, I still don't fully understand how it works, but it works, so that's good for now.

### 2. Bug#2: Radio in useFieldArray

#### 💥 What Happened

I was creating a simple list, where each item had a "name" and a "value determined by the radio selection."

However, when I rearranged the items, I encountered an issue where the radio button selection stopped responding.

#### 🤯 My thoughts at the time

In this case, the nesting level was low, so the cause was found relatively quickly. A good rule of thumb is to first check whether the checked setting is set correctly when the radio selection state doesn't change.

#### ✅ Solution

Here is the code with the bug:

```javascript!
{SELECTION_PROCESS_OPTIONS.map((option, optionId) => (
 <Controller
  key={optionId}
  name={`items.${statusIndex}.flowOrder`}
  control={control}
  render={({ field: { value } }) => (
   <Radio
    label={option.label}
    value={option.value}
    checked={value === option.value}
    {...register(`items.${statusIndex}.flowOrder` as const)}
   />
  )}
 />
))}
```

And here is the modified code:

```javascript!
{SELECTION_PROCESS_OPTIONS.map((option, optionIndex) => (
 <Radio
  key={optionIndex}
  label={option.label}
  value={option.value}
  checked={watchItems[statusIndex].flowOrder === option.value}
  {...register(`items.${statusIndex}.flowOrder` as const)}
  />
))}
```

The cause was that the `value` received via the `Controller` had become outdated and had not been updated.
So I used `watch()` to monitor the entire array and reference the real-time values, which neatly solved the problem.

### 3. Conclusion

The big lesson learned from these two bugs is not to overuse `Controllers`. While they are convenient for integrating with UI libraries, they can cause unexpected behavior, especially when combined with dynamic fields like `useFieldArray`.

If you're using a `Controller` and values aren't updating correctly, you can try using `register()`. Also, pay close attention to the `checked` state of radio buttons. In surprisingly many cases, the cause of the bug lies there.

The cause of the bug can sometimes be lurking deep in the code. Carefully addressing even the smallest inconsistencies may be the shortcut to a stable implementation.

<small>
    Published date: 2025-07-07 <br/>
    Also published <a href="https://josysnavi.jp/2025/rare-bugs-on-usefieldarray">here</a>.
</small>