ronantakizawa/codereview-bench huggingface dataset:
Repository: react-hook-form/react-hook-form
File: src/useFieldArray.test.tsx (TypeScript)

Code before:
            {
              test: 1,
            },
            {
              test1: 1,
            },
            {
              test2: 1,
            },
          ],
        },
      };

      const { result } = renderHook(() =>
        useFieldArray({
          control: reconfigureControl({
            defaultValuesRef: {
              current: { test: [{ test: '1' }, { test: '2' }] },
            },
            fieldsRef: {
              current: {
                'test[0]': { ref: { name: 'test[0]', value: { test: '1' } } },
                'test[1]': { ref: { name: 'test[1]', value: { test: '2' } } },
              },
            },
            getValues: () => ({ test: [] }),
            readFormStateRef: {
              current: {
                dirtyFields: true,
              },
            } as any,
            dirtyFieldsRef,
          }),
          name: 'test',
        }),
      );

      act(() => {
        result.current.swap(0, 1);
      });

      expect(result.current.fields).toEqual([
        { id: '1', test: '2' },
        { id: '1', test: '1' },
      ]);

      expect(dirtyFieldsRef.current).toEqual({
        test: [
          {
            test1: 1,
          },

Review comment (suggestion):
I think those tests will all have to rewrite the way @keiya01 is written, more of integration tests then just test `useFieldArray`. 

Code after:
            {
              test2: 1,
            },
          ],
        },
      };

      const { result } = renderHook(() =>
        useFieldArray({
          control: reconfigureControl({
            defaultValuesRef: {
              current: { test: [{ test: '1' }, { test: '2' }] },
            },
            fieldsRef: {
              current: {
                'test[0]': { ref: { name: 'test[0]', value: { test: '1' } } },
                'test[1]': { ref: { name: 'test[1]', value: { test: '2' } } },
              },
            },
            readFormStateRef: {
              current: {
                dirtyFields: true,
              },
            } as any,
            dirtyFieldsRef,
          }),
          name: 'test',
        }),
      );

      act(() => {
        result.current.swap(0, 1);
      });

      expect(result.current.fields).toEqual([
        { id: '1', test: '2' },
        { id: '1', test: '1' },
      ]);

      expect(dirtyFieldsRef.current).toEqual({
        test: [
          {
            test1: 1,
          },
          {
            test: 1,
          },
          {
            test2: 1,
          },
        ],
Repository: react-hook-form/react-hook-form
File: src/useForm.test.tsx (TypeScript)

Code before:
  describe('mode with onTouch', () => {
    it('should validate form only when input is been touched', async () => {
      const Component = () => {
        const { register, errors } = useForm({
          mode: 'onTouch',
        });

        return (
          <>
            <input
              type="text"
              name="test"
              ref={register({ required: 'This is required.' })}
            />
            {errors.test?.message}
          </>
        );
      };

      render(<Component />);

      screen.getByRole('textbox').focus();

      await actComponent(async () => {
        await fireEvent.blur(screen.getByRole('textbox'));
      });

      expect(screen.getByText('This is required.')).toBeInTheDocument();

      await actComponent(async () => {
        await fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: 'test',
          },
        });
      });

      expect(screen.queryByText('This is required.')).not.toBeInTheDocument();

      await actComponent(async () => {
        fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: '',
          },
        });
      });

      expect(screen.getByText('This is required.')).toBeInTheDocument();
    });
  });
});

Review comment (suggestion):
Kinda confuse, will it trigger also even without doing blur event? because in my understanding, `onTouch` will validate the moment I focus/touch the field, right? and then again, you triggered the `onChange` function then validation run, but should it run? I'm kinda confuse with this behavior. I'm good with this feature just confuse sorry :sweat_smile: 

Code after:
  describe('mode with onTouched', () => {
    it('should validate form only when input is been touched', async () => {
      const Component = () => {
        const { register, errors } = useForm({
          mode: 'onTouched',
        });

        return (
          <>
            <input
              type="text"
              name="test"
              ref={register({ required: 'This is required.' })}
            />
            {errors.test?.message}
          </>
        );
      };

      render(<Component />);

      screen.getByRole('textbox').focus();

      await actComponent(async () => {
        await fireEvent.blur(screen.getByRole('textbox'));
      });

      expect(screen.queryByText('This is required.')).toBeInTheDocument();

      await actComponent(async () => {
        await fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: 'test',
          },
        });
      });

      expect(screen.queryByText('This is required.')).not.toBeInTheDocument();

      await actComponent(async () => {
        fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: '',
          },
        });
      });

      expect(screen.queryByText('This is required.')).toBeInTheDocument();
    });
  });
});
Repository: react-hook-form/react-hook-form
File: src/useForm.test.tsx (TypeScript)

Code before:
      const Component = () => {
        const { register, errors } = useForm({
          mode: 'onTouched',
        });

        return (
          <>
            <input
              type="text"
              name="test"
              ref={register({ required: 'This is required.' })}
            />
            {errors.test?.message}
          </>
        );
      };

      render(<Component />);

      screen.getByRole('textbox').focus();

      await actComponent(async () => {
        await fireEvent.blur(screen.getByRole('textbox'));
      });

      expect(screen.getByText('This is required.')).toBeInTheDocument();

      await actComponent(async () => {
        await fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: 'test',
          },
        });
      });

      expect(screen.queryByText('This is required.')).not.toBeInTheDocument();

      await actComponent(async () => {
        fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: '',
          },
        });
      });

      expect(screen.getByText('This is required.')).toBeInTheDocument();
    });
  });
});


Review comment (suggestion):
```suggestion
      expect(screen.queryByText('This is required.')).toBeInTheDocument();
```

I think you should `screen.queryByText()` because `getBy*` method throw error when specified element could not found.

Code after:
      const Component = () => {
        const { register, errors } = useForm({
          mode: 'onTouched',
        });

        return (
          <>
            <input
              type="text"
              name="test"
              ref={register({ required: 'This is required.' })}
            />
            {errors.test?.message}
          </>
        );
      };

      render(<Component />);

      screen.getByRole('textbox').focus();

      await actComponent(async () => {
        await fireEvent.blur(screen.getByRole('textbox'));
      });

      expect(screen.queryByText('This is required.')).toBeInTheDocument();

      await actComponent(async () => {
        await fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: 'test',
          },
        });
      });

      expect(screen.queryByText('This is required.')).not.toBeInTheDocument();

      await actComponent(async () => {
        fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: '',
          },
        });
      });

      expect(screen.queryByText('This is required.')).toBeInTheDocument();
    });
  });
});
Repository: react-hook-form/react-hook-form
File: src/useForm.test.tsx (TypeScript)

Code before:

      await actComponent(async () => {
        await fireEvent.blur(screen.getByRole('textbox'));
      });

      expect(screen.getByText('This is required.')).toBeInTheDocument();

      await actComponent(async () => {
        await fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: 'test',
          },
        });
      });

      expect(screen.queryByText('This is required.')).not.toBeInTheDocument();

      await actComponent(async () => {
        fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: '',
          },
        });
      });

      expect(screen.getByText('This is required.')).toBeInTheDocument();
    });
  });
});


Review comment (suggestion):
```suggestion
      expect(screen.queryByText('This is required.')).toBeInTheDocument();
```

Code after:

      await actComponent(async () => {
        await fireEvent.blur(screen.getByRole('textbox'));
      });

      expect(screen.queryByText('This is required.')).toBeInTheDocument();

      await actComponent(async () => {
        await fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: 'test',
          },
        });
      });

      expect(screen.queryByText('This is required.')).not.toBeInTheDocument();

      await actComponent(async () => {
        fireEvent.input(screen.getByRole('textbox'), {
          target: {
            value: '',
          },
        });
      });

      expect(screen.queryByText('This is required.')).toBeInTheDocument();
    });
  });
});
Repository: react-hook-form/react-hook-form
File: src/useFieldArray.test.tsx (TypeScript)

Code before:
              <div key={i.toString()}>
                <input
                  name={`test[${i}].name`}
                  ref={register()}
                  defaultValue={field.name}
                />
                <button type={'button'} onClick={() => remove(i)}>
                  remove
                </button>
              </div>
            ))}

            <button type={'button'} onClick={() => append({})}>
              append
            </button>
          </form>
        );
      };

      render(<Component />);

      expect(formState.isDirty).toBeFalsy();

      await actComponent(async () => {
        await fireEvent.click(screen.getByRole('button', { name: /append/i }));
      });

      expect(formState.isDirty).toBeTruthy();

      await actComponent(async () => {
        await fireEvent.click(
          screen.getAllByRole('button', { name: /remove/i })[1],
        );
      });

      expect(formState.isDirty).toBeFalsy();
    });

    it('should remove field according index', () => {
      const dirtyFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const touchedFieldsRef = {
        current: {
          test: [true, true],
        },
      };


Review comment (suggestion):
```suggestion
      fireEvent.click(screen.getByRole('button', { name: /append/i }));
```

Code after:
              <div key={i.toString()}>
                <input
                  name={`test[${i}].name`}
                  ref={register()}
                  defaultValue={field.name}
                />
                <button type={'button'} onClick={() => remove(i)}>
                  remove
                </button>
              </div>
            ))}

            <button type={'button'} onClick={() => append({})}>
              append
            </button>
          </form>
        );
      };

      render(<Component />);

      expect(formState.isDirty).toBeFalsy();

      fireEvent.click(screen.getByRole('button', { name: /append/i }));

      expect(formState.isDirty).toBeTruthy();

      fireEvent.click(screen.getAllByRole('button', { name: /remove/i })[1]);

      expect(formState.isDirty).toBeFalsy();
    });

    it('should remove field according index', () => {
      const dirtyFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const touchedFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const { result } = renderHook(() =>
        useFieldArray({
          control: {
            ...reconfigureControl({
              defaultValuesRef: {
                current: { test: [{ test: '1' }, { test: '2' }] },
Repository: react-hook-form/react-hook-form
File: src/useFieldArray.test.tsx (TypeScript)

Code before:
                </button>
              </div>
            ))}

            <button type={'button'} onClick={() => append({})}>
              append
            </button>
          </form>
        );
      };

      render(<Component />);

      expect(formState.isDirty).toBeFalsy();

      await actComponent(async () => {
        await fireEvent.click(screen.getByRole('button', { name: /append/i }));
      });

      expect(formState.isDirty).toBeTruthy();

      await actComponent(async () => {
        await fireEvent.click(
          screen.getAllByRole('button', { name: /remove/i })[1],
        );
      });

      expect(formState.isDirty).toBeFalsy();
    });

    it('should remove field according index', () => {
      const dirtyFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const touchedFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const { result } = renderHook(() =>
        useFieldArray({
          control: {
            ...reconfigureControl({
              defaultValuesRef: {
                current: { test: [{ test: '1' }, { test: '2' }] },
              },
              readFormStateRef: {

Review comment (suggestion):
```suggestion
      fireEvent.click(
        screen.getAllByRole('button', { name: /remove/i })[1],
      );
```

Code after:
                </button>
              </div>
            ))}

            <button type={'button'} onClick={() => append({})}>
              append
            </button>
          </form>
        );
      };

      render(<Component />);

      expect(formState.isDirty).toBeFalsy();

      fireEvent.click(screen.getByRole('button', { name: /append/i }));

      expect(formState.isDirty).toBeTruthy();

      fireEvent.click(screen.getAllByRole('button', { name: /remove/i })[1]);

      expect(formState.isDirty).toBeFalsy();
    });

    it('should remove field according index', () => {
      const dirtyFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const touchedFieldsRef = {
        current: {
          test: [true, true],
        },
      };

      const { result } = renderHook(() =>
        useFieldArray({
          control: {
            ...reconfigureControl({
              defaultValuesRef: {
                current: { test: [{ test: '1' }, { test: '2' }] },
              },
              readFormStateRef: {
                current: {
                  touched: true,
                  dirtyFields: true,
                },
              } as any,
              fieldsRef: {
Repository: react-hook-form/react-hook-form
File: src/useFieldArray.test.tsx (TypeScript)

Code before:
                  remove
                </button>
              </div>
            ))}

            <button type={'button'} onClick={() => append({})}>
              append
            </button>
          </form>
        );
      };

      render(<Component />);

      expect(formState.isDirty).toBeFalsy();

      fireEvent.click(screen.getByRole('button', { name: /append/i }));

      expect(formState.isDirty).toBeTruthy();

      fireEvent.click(screen.getAllByRole('button', { name: /remove/i })[1]);

      expect(formState.isDirty).toBeFalsy();
    });

    it('should update isValid formState when item removed', async () => {
      let formState: any;
      const Component = () => {
        const { register, control, formState: tempFormState } = useForm({
          defaultValues: {
            test: [{ name: 'default' }],
          },
        });
        const { fields, remove, append } = useFieldArray({
          name: 'test',
          control,
        });

        formState = tempFormState;

        formState.isValid;

        return (
          <form>
            {fields.map((field, i) => (
              <div key={i.toString()}>
                <input
                  name={`test[${i}].name`}
                  ref={register({ required: true })}
                  defaultValue={field.name}
                />

Review comment (bug):
@keiya01 could you please take a look at this test? why it's failing? I have test it the code functional and ti's working 🤔 

https://codesandbox.io/s/formstate-is-not-still-valid-after-removing-items-by3e7?file=/src/App.js:1629-1636

Code after:
                  remove
                </button>
              </div>
            ))}

            <button type={'button'} onClick={() => append({})}>
              append
            </button>
          </form>
        );
      };

      render(<Component />);

      expect(formState.isDirty).toBeFalsy();

      fireEvent.click(screen.getByRole('button', { name: /append/i }));

      expect(formState.isDirty).toBeTruthy();

      fireEvent.click(screen.getAllByRole('button', { name: /remove/i })[1]);

      expect(formState.isDirty).toBeFalsy();
    });

    it('should update isValid formState when item removed', async () => {
      let formState: any;
      const Component = () => {
        const { register, control, formState: tempFormState } = useForm({
          mode: 'onChange',
          defaultValues: {
            test: [{ name: 'default' }],
          },
        });
        const { fields, remove, append } = useFieldArray({
          name: 'test',
          control,
        });

        formState = tempFormState;

        formState.isValid;

        return (
          <form>
            {fields.map((field, i) => (
              <div key={i.toString()}>
                <input
                  name={`test[${i}].name`}
                  ref={register({ required: true })}
                  defaultValue={field.name}
Repository: react-hook-form/react-hook-form
File: src/useForm.ts (TypeScript)

Code before:
    isValid: isOnSubmit
      ? isSubmittedRef.current && isEmptyObject(errorsRef.current)
      : isValidRef.current,
  };

  const commonProps = {
    trigger,
    setValue: React.useCallback(setValue, [
      reRender,
      setInternalValue,
      trigger,
    ]),
    getValues: React.useCallback(getValues, []),
    register: React.useCallback(register, [defaultValuesRef.current]),
    unregister: React.useCallback(unregister, []),
    formState: isProxyEnabled
      ? new Proxy<FormStateProxy<TFieldValues>>(formState, {
          get: (obj, prop: keyof FormStateProxy) => {
            if (
              process.env.NODE_ENV !== 'production' &&
              prop === 'isValid' &&
              isOnSubmit
            ) {
              // eslint-disable-next-line no-console
              console.warn(
                'formState.isValid is only applicable with onChange and onBlur mode. Please see https://react-hook-form.com/api#formState',
              );
            }

            if (prop in obj) {
              readFormStateRef.current[prop] = true;
              return obj[prop];
            }

            return undefined;
          },
        })
      : formState,
  };

  const control = {
    removeFieldEventListener,
    renderWatchedInputs,
    watchInternal,
    reRender,
    mode: modeRef.current,
    reValidateMode: {
      isReValidateOnBlur,
      isReValidateOnChange,
    },
    errorsRef,

Review comment (suggestion):
```suggestion
                'formState.isValid is applicable with onChange and onBlur mode. https://react-hook-form.com/api#formState',
```

Code after:
    isValid: isOnSubmit
      ? isSubmittedRef.current && isEmptyObject(errorsRef.current)
      : isValidRef.current,
  };

  const commonProps = {
    trigger,
    setValue: React.useCallback(setValue, [
      reRender,
      setInternalValue,
      trigger,
    ]),
    getValues: React.useCallback(getValues, []),
    register: React.useCallback(register, [defaultValuesRef.current]),
    unregister: React.useCallback(unregister, []),
    formState: isProxyEnabled
      ? new Proxy<FormStateProxy<TFieldValues>>(formState, {
          get: (obj, prop: keyof FormStateProxy) => {
            if (
              process.env.NODE_ENV !== 'production' &&
              prop === 'isValid' &&
              isOnSubmit
            ) {
              // eslint-disable-next-line no-console
              console.warn(
                'formState.isValid is applicable with onChange and onBlur mode. https://react-hook-form.com/api#formState',
              );
            }

            if (prop in obj) {
              readFormStateRef.current[prop] = true;
              return obj[prop];
            }

            return undefined;
          },
        })
      : formState,
  };

  const control = {
    removeFieldEventListener,
    renderWatchedInputs,
    watchInternal,
    reRender,
    mode: modeRef.current,
    reValidateMode: {
      isReValidateOnBlur,
      isReValidateOnChange,
    },
    errorsRef,