ronantakizawa/codereview-bench huggingface dataset:
Repository: react-hook-form/react-hook-form
File: src/utils/onDomRemove.ts (TypeScript)

Code before:
import * as React from 'react';
import { Field, FieldRefs } from '../types/form';
import isDetached from './isDetached';

export default function onDomRemove<TFieldValues>(
  fieldsRef: React.MutableRefObject<FieldRefs<TFieldValues>>,
  removeFieldEventListenerAndRef: (
    field: Field | undefined,
    forceDelete?: boolean,
  ) => void,
): MutationObserver {
  const observer = new MutationObserver((): void => {
    for (const field of Object.values(fieldsRef.current)) {
      if (field) {
        if (field.options) {
          for (const { ref } of field.options) {
            if (isDetached(ref)) {
              removeFieldEventListenerAndRef(field);
            }
          }
        } else if (isDetached(field.ref)) {
          removeFieldEventListenerAndRef(field);
        }
      }
    }
  });

  observer.observe(window.document, {
    childList: true,
    subtree: true,
  });

  return observer;
}


Review comment (suggestion):
```suggestion
      if (field && field.options) {
        for (const { ref } of field.options) {
          if (isDetached(ref)) {
            removeFieldEventListenerAndRef(field);
          }
        }
      } else if (isDetached(field.ref)) {
        removeFieldEventListenerAndRef(field);
      }
```

Code after:
import * as React from 'react';
import { Field, FieldRefs } from '../types/form';
import isDetached from './isDetached';

export default function onDomRemove<TFieldValues>(
  fieldsRef: React.MutableRefObject<FieldRefs<TFieldValues>>,
  removeFieldEventListenerAndRef: (
    field: Field | undefined,
    forceDelete?: boolean,
  ) => void,
): MutationObserver {
  const observer = new MutationObserver((): void => {
    for (const field of Object.values(fieldsRef.current)) {
      if (field && field.options) {
        for (const { ref } of field.options) {
          if (isDetached(ref)) {
            removeFieldEventListenerAndRef(field);
          }
        }
      } else if (field && isDetached(field.ref)) {
        removeFieldEventListenerAndRef(field);
      }
    }
  });

  observer.observe(window.document, {
    childList: true,
    subtree: true,
  });

  return observer;
}
Repository: react-hook-form/react-hook-form
File: src/useForm.ts (TypeScript)

Code before:
    watchFieldsRef.current.has((name.match(/\w+/) || [])[0]);

  const renderWatchedInputs = (name: string, found = true): boolean => {
    if (!isEmptyObject(useWatchFieldsRef.current)) {
      for (const key in useWatchFieldsRef.current) {
        if (
          !name ||
          useWatchFieldsRef.current[key].has(name) ||
          useWatchFieldsRef.current[key].has(getFieldArrayParentName(name)) ||
          !useWatchFieldsRef.current[key].size
        ) {
          useWatchRenderFunctionsRef.current[key]();
          found = false;
        }
      }
    }

    return found;
  };

  function setValue<
    TFieldName extends string,
    TFieldValue extends TFieldValues[TFieldName]
  >(
    name: TFieldName,
    value?: NonUndefined<TFieldValue> extends NestedValue<infer U>
      ? U
      : UnpackNestedValue<DeepPartial<LiteralToPrimitive<TFieldValue>>>,
    config: SetValueConfig = {},
  ): void {
    setInternalValue(name, value as TFieldValues[string], config);

    if (isFieldWatched(name)) {
      updateFormState();
    }

    renderWatchedInputs(name);

    if (config.shouldValidate) {
      trigger(name as any);
    }
  }

  handleChangeRef.current = handleChangeRef.current
    ? handleChangeRef.current
    : async ({ type, target }: Event): Promise<void | boolean> => {
        const name = (target as Ref)!.name;
        const field = fieldsRef.current[name];
        let error;
        let isValid;


Review comment (suggestion):
```suggestion
    value: NonUndefined<TFieldValue> extends NestedValue<infer U>
```

Code after:
            );

            updateFormState({
              isDirty: !deepEqual(
                { ...getValues(), [name]: value },
                defaultValuesRef.current,
              ),
              dirtyFields: formStateRef.current.dirtyFields,
            });
          }
        }
      }

      !shouldUnregister && set(shallowFieldsStateRef.current, name, value);
    },
    [updateAndGetDirtyState, setFieldValue, setInternalValues],
  );

  const isFieldWatched = (name: string) =>
    isWatchAllRef.current ||
    watchFieldsRef.current.has(name) ||
    watchFieldsRef.current.has((name.match(/\w+/) || [])[0]);

  const renderWatchedInputs = (name: string, found = true): boolean => {
    if (!isEmptyObject(useWatchFieldsRef.current)) {
      for (const key in useWatchFieldsRef.current) {
        if (
          !name ||
          useWatchFieldsRef.current[key].has(name) ||
          useWatchFieldsRef.current[key].has(getFieldArrayParentName(name)) ||
          !useWatchFieldsRef.current[key].size
        ) {
          useWatchRenderFunctionsRef.current[key]();
          found = false;
        }
      }
    }

    return found;
  };

  function setValue<
    TFieldName extends string,
    TFieldValue extends TFieldValues[TFieldName]
  >(
    name: TFieldName,
    value:
      | (NonUndefined<TFieldValue> extends NestedValue<infer U>
          ? U
          : UnpackNestedValue<DeepPartial<LiteralToPrimitive<TFieldValue>>>)
      | null
Repository: react-hook-form/react-hook-form
File: src/utils/cloneObject.test.ts (TypeScript)

Code before:
        test: '12',
        test1: [1, 2, 3, 4],
        date: new Date('2020-10-15'),
        deep: {
          date: new Date('2020-10-15'),
        },
      },
    };

    const copy = cloneObject(data);
    expect(cloneObject(data)).toEqual(copy);

    // @ts-ignore
    copy.test.what = '1243';
    copy.test.date = new Date('2020-10-116');

    expect(data).toEqual({
      test: {
        test: '12',
        test1: [1, 2, 3, 4],
        date: new Date('2020-10-15'),
        deep: {
          date: new Date('2020-10-15'),
        },
      },
    });
  });
});


Review comment (suggestion):
Just adding to the verboseness of the test. May not be perfectly formatted.
```suggestion
    const data = {
      test: {
        date: new Date('2020-10-15'),
        test0: 12,
        test1: '12',
        test2: [1, 2, 3, 4],
        deep: {
          date: new Date('2020-10-15'),
          test0: 12,
          test1: '12',
          test2: [1, 2, 3, 4],
        },
      },
    };

    const copy = cloneObject(data);
    expect(cloneObject(data)).toEqual(copy);

    // @ts-ignore
    copy.test.what = '1243';
    copy.test.date = new Date('2020-10-116');

    expect(data).toEqual({
      test: {
        date: new Date('2020-10-15'),
        test0: 12,
        test1: '12',
        test2: [1, 2, 3, 4],
        deep: {
          date: new Date('2020-10-15'),
          test0: 12,
          test1: '12',
          test2: [1, 2, 3, 4],
        },
      },
    });
```

Code after:
        date: new Date('2020-10-15'),
        test0: 12,
        test1: '12',
        test2: [1, 2, 3, 4],
        deep: {
          date: new Date('2020-10-15'),
          test0: 12,
          test1: '12',
          test2: [1, 2, 3, 4],
        },
      },
    };

    const copy = cloneObject(data);
    expect(cloneObject(data)).toEqual(copy);

    // @ts-ignore
    copy.test.what = '1243';
    copy.test.date = new Date('2020-10-116');

    expect(data).toEqual({
      test: {
        date: new Date('2020-10-15'),
        test0: 12,
        test1: '12',
        test2: [1, 2, 3, 4],
        deep: {
          date: new Date('2020-10-15'),
          test0: 12,
          test1: '12',
          test2: [1, 2, 3, 4],
        },
      },
    });
  });
});
Repository: react-hook-form/react-hook-form
File: src/utils/cloneObject.ts (TypeScript)

Code before:
import isPrimitive from './isPrimitive';
import { UNDEFINED } from '../constants';

const isWeb = typeof window !== UNDEFINED;

export default function cloneObject<T extends unknown>(data: T): T {
  let copy: any;

  if (isPrimitive(data) || (isWeb && data instanceof File)) {
    return data;
  }

  if (data instanceof Date) {
    copy = new Date(data.getTime());
    return copy;
  }

  if (data instanceof Set) {
    copy = new Set();
    for (const item of data) {
      copy.add(item);
    }
    return copy;
  }

  if (data instanceof Map) {
    copy = new Map();
    for (const key of data.keys()) {
      copy.set(key, cloneObject(data.get(key)));

Review comment (suggestion):
```suggestion
const isWeb = typeof window !== UNDEFINED && !isUndefined(HTMLElement);
```

Code after:
import isPrimitive from './isPrimitive';
import isWeb from './isWeb';

export default function cloneObject<T extends unknown>(data: T): T {
  let copy: any;

  if (isPrimitive(data) || (isWeb && data instanceof File)) {
    return data;
  }

  if (data instanceof Date) {
    copy = new Date(data.getTime());
    return copy;
  }

  if (data instanceof Set) {
    copy = new Set();
    for (const item of data) {
      copy.add(item);
    }
    return copy;
  }

  if (data instanceof Map) {
    copy = new Map();
    for (const key of data.keys()) {
      copy.set(key, cloneObject(data.get(key)));
    }
    return copy;
Repository: react-hook-form/react-hook-form
File: src/types/resolvers.ts (TypeScript)

Code before:
import { EmptyObject } from './utils';
import { CriteriaMode, UnpackNestedValue } from './form';
import { Field, FieldValues } from './fields';
import { FieldErrors } from './errors';

export type ResolverSuccess<TFieldValues extends FieldValues = FieldValues> = {
  values: UnpackNestedValue<TFieldValues>;
  errors: EmptyObject;
};

export type ResolverError<TFieldValues extends FieldValues = FieldValues> = {
  values: EmptyObject;
  errors: FieldErrors<TFieldValues>;
};

export type ResolverResult<TFieldValues extends FieldValues = FieldValues> =
  | ResolverSuccess<TFieldValues>
  | ResolverError<TFieldValues>;

export interface ResolverOptions {
  criteriaMode?: CriteriaMode;
  fields?: Field['__field'][];
}

export type Resolver<
  TFieldValues extends FieldValues = FieldValues,
  TContext extends object = object
> = (
  values: UnpackNestedValue<TFieldValues>,
  context?: TContext,
  options?: ResolverOptions,
) => Promise<ResolverResult<TFieldValues>> | ResolverResult<TFieldValues>;


Review comment (suggestion):
instead of an array of `fields`, maybe we can just pass the entire `fieldsRef`?

```tsx
async (data, context, { fields }) => {
  // when generate the errors object in resolver, you can look up the fields object and include the `refs`
}
```

Code after:
import { EmptyObject } from './utils';
import { CriteriaMode, UnpackNestedValue } from './form';
import { Field, FieldName, FieldValues, InternalFieldName } from './fields';
import { FieldErrors } from './errors';

export type ResolverSuccess<TFieldValues extends FieldValues = FieldValues> = {
  values: UnpackNestedValue<TFieldValues>;
  errors: EmptyObject;
};

export type ResolverError<TFieldValues extends FieldValues = FieldValues> = {
  values: EmptyObject;
  errors: FieldErrors<TFieldValues>;
};

export type ResolverResult<TFieldValues extends FieldValues = FieldValues> =
  | ResolverSuccess<TFieldValues>
  | ResolverError<TFieldValues>;

export interface ResolverOptions<TFieldValues> {
  criteriaMode?: CriteriaMode;
  fields: Record<InternalFieldName, Field['__field']>;
  names?: FieldName<TFieldValues>[];
}

export type Resolver<
  TFieldValues extends FieldValues = FieldValues,
  TContext extends object = object
> = (
  values: UnpackNestedValue<TFieldValues>,
  context: TContext | undefined,
  options: ResolverOptions<TFieldValues>,
) => Promise<ResolverResult<TFieldValues>> | ResolverResult<TFieldValues>;
Repository: react-hook-form/react-hook-form
File: src/useForm.ts (TypeScript)

Code before:
          return false;
        }
      }

      const error = (
        await validateField(
          get(fieldsRef.current, name) as Field,
          isValidateAllFieldCriteria,
        )
      )[name];

      shouldRenderBaseOnError(name, error, skipReRender);

      return isUndefined(error);
    },
    [shouldRenderBaseOnError, isValidateAllFieldCriteria],
  );

  const executeSchemaOrResolverValidation = React.useCallback(
    async (
      names: InternalFieldName[],
      currentNames: FieldName<TFieldValues>[] = [],
    ) => {
      const currentFields: Field['__field'][] = [];
      for (const name of currentNames) {
        const field = fieldsRef.current[name];
        if (field) {
          currentFields.push(field.__field);
        }
      }

      const { errors } = await resolverRef.current!(
        getValues(),
        contextRef.current,
        {
          criteriaMode,
          fields: currentFields.length ? currentFields : undefined,
        },
      );

      for (const name of names) {
        const error = get(errors, name);
        error
          ? set(formStateRef.current.errors, name, error)
          : unset(formStateRef.current.errors, name);
      }

      return errors;
    },
    [shouldRenderBaseOnError, criteriaMode],
  );

Review comment (bug):
This is probably going to fail with deeply nested field input. maybe use `get` ?

Code after:
      if (process.env.NODE_ENV !== 'production') {
        if (!get(fieldsRef.current, name)) {
          console.warn('📋 Field is missing with `name` attribute: ', name);
          return false;
        }
      }

      const error = (
        await validateField(
          get(fieldsRef.current, name) as Field,
          isValidateAllFieldCriteria,
        )
      )[name];

      shouldRenderBaseOnError(name, error, skipReRender);

      return isUndefined(error);
    },
    [shouldRenderBaseOnError, isValidateAllFieldCriteria],
  );

  const executeSchemaOrResolverValidation = React.useCallback(
    async (
      names: InternalFieldName[],
      currentNames: FieldName<TFieldValues>[] = [],
    ) => {
      const { errors } = await resolverRef.current!(
        getValues(),
        contextRef.current,
        {
          criteriaMode,
          names: currentNames,
          fields: getFields(fieldsNamesRef.current, fieldsRef.current),
        },
      );

      for (const name of names) {
        const error = get(errors, name);
        error
          ? set(formStateRef.current.errors, name, error)
          : unset(formStateRef.current.errors, name);
      }

      return errors;
    },
    [shouldRenderBaseOnError, criteriaMode],
  );

  const validateForm = async (fieldsRef: FieldRefs) => {
    for (const name in fieldsRef) {
      const field = fieldsRef[name];
Repository: react-hook-form/react-hook-form
File: src/useForm.ts (TypeScript)

Code before:
        if (!get(fieldsRef.current, name)) {
          console.warn('📋 Field is missing with `name` attribute: ', name);
          return false;
        }
      }

      const error = (
        await validateField(
          get(fieldsRef.current, name) as Field,
          isValidateAllFieldCriteria,
        )
      )[name];

      shouldRenderBaseOnError(name, error, skipReRender);

      return isUndefined(error);
    },
    [shouldRenderBaseOnError, isValidateAllFieldCriteria],
  );

  const executeSchemaOrResolverValidation = React.useCallback(
    async (
      names: InternalFieldName[],
      currentNames: FieldName<TFieldValues>[] = [],
    ) => {
      const currentFields: Field['__field'][] = [];
      for (const name of currentNames) {
        const field = get(fieldsRef.current, name);
        if (field) {
          currentFields.push(field.__field);
        }
      }

      const { errors } = await resolverRef.current!(
        getValues(),
        contextRef.current,
        {
          criteriaMode,
          fields: currentFields.length ? currentFields : undefined,
        },
      );

      for (const name of names) {
        const error = get(errors, name);
        error
          ? set(formStateRef.current.errors, name, error)
          : unset(formStateRef.current.errors, name);
      }

      return errors;
    },

Review comment (suggestion):
I think this works for deep nested: 

```ts
let currentFields = {};

for (name in fieldsNamesRef.current) {
  const field = get(fieldsRef.current, name);
  
  field && currentFields[name] =  field.__field;
}
```

Code after:
      skipReRender?: boolean | null,
    ): Promise<boolean> => {
      if (process.env.NODE_ENV !== 'production') {
        if (!get(fieldsRef.current, name)) {
          console.warn('📋 Field is missing with `name` attribute: ', name);
          return false;
        }
      }

      const error = (
        await validateField(
          get(fieldsRef.current, name) as Field,
          isValidateAllFieldCriteria,
        )
      )[name];

      shouldRenderBaseOnError(name, error, skipReRender);

      return isUndefined(error);
    },
    [shouldRenderBaseOnError, isValidateAllFieldCriteria],
  );

  const executeSchemaOrResolverValidation = React.useCallback(
    async (
      names: InternalFieldName[],
      currentNames: FieldName<TFieldValues>[] = [],
    ) => {
      const { errors } = await resolverRef.current!(
        getValues(),
        contextRef.current,
        {
          criteriaMode,
          names: currentNames,
          fields: getFields(fieldsNamesRef.current, fieldsRef.current),
        },
      );

      for (const name of names) {
        const error = get(errors, name);
        error
          ? set(formStateRef.current.errors, name, error)
          : unset(formStateRef.current.errors, name);
      }

      return errors;
    },
    [shouldRenderBaseOnError, criteriaMode],
  );

  const validateForm = async (fieldsRef: FieldRefs) => {
Repository: react-hook-form/react-hook-form
File: scripts/jest/jest.config.js (JavaScript)

Code before:
/* eslint-disable @typescript-eslint/no-var-requires */
const { defaults: tsjPresets } = require('ts-jest/presets');
const jestPresets = require('@testing-library/react-native/jest-preset');

const common = {
  rootDir: '.',
  roots: ['<rootDir>/src'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.jest.json',
    },
  },
  transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'],
  moduleFileExtensions: ['ts', 'tsx', 'js'],
};

const web = {
  ...common,
  displayName: {
    name: 'Web',
    color: 'cyan',
  },
  testMatch: ['**/__tests__/**/*.[jt]s?(x)'],
  setupFilesAfterEnv: ['<rootDir>/scripts/jest/setup.ts'],
};

const server = {
  ...common,
  displayName: {
    name: 'Server',

Review comment (suggestion):
holy shit! I have been writing those `before` `after` all those years, turn out there is a bloody config... thank you @jorisre 🙏

Code after:
/* eslint-disable @typescript-eslint/no-var-requires */
const { defaults: tsjPresets } = require('ts-jest/presets');
const jestPresets = require('@testing-library/react-native/jest-preset');

const common = {
  clearMocks: true,
  resetMocks: true,
  restoreMocks: true,
  rootDir: '.',
  roots: ['<rootDir>/src'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.jest.json',
    },
  },
  transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'],
  moduleFileExtensions: ['ts', 'tsx', 'js'],
};

const web = {
  ...common,
  displayName: {
    name: 'Web',
    color: 'cyan',
  },
  testMatch: ['**/__tests__/**/*.[jt]s?(x)'],
  setupFilesAfterEnv: ['<rootDir>/scripts/jest/setup.ts'],
};

const server = {
Repository: react-hook-form/react-hook-form
File: app/src/formState.tsx (TypeScript)

Code before:
    formState: {
      dirtyFields,
      isSubmitted,
      submitCount,
      touched,
      isDirty,
      isSubmitting,
      isSubmitSuccessful,
      isValid,
    },
    reset,
  } = useForm<{
    firstName: string;
    lastName: string;
    select: string;
    radio: string;
    checkbox: boolean;
    ['checkbox-checked']: boolean;
  }>({
    mode: props.match.params.mode,
    defaultValues: {
      firstName: '',
      lastName: '',
      select: '',
      checkbox: false,
      radio: undefined,
      'checkbox-checked': true,
    },
  });

  renderCounter++;

  return (
    <form onSubmit={handleSubmit(() => {})}>
      <input
        name="firstName"
        ref={register({ required: true })}
        placeholder="firstName"
      />
      <input
        name="lastName"
        ref={register({ required: true })}
        placeholder="lastName"
      />
      <div id="state">
        {JSON.stringify({
          isSubmitted,
          submitCount,
          isDirty,
          isSubmitting,
          isSubmitSuccessful,

Review comment (bug):
@bluebill1049  Hi
can you please check if this bug reproduced for input type="hidden" ? out dropdown based on hidden input and have same problem 
thank you 🙂 ❤️

Code after:
    formState: {
      dirtyFields,
      isSubmitted,
      submitCount,
      touched,
      isDirty,
      isSubmitting,
      isSubmitSuccessful,
      isValid,
    },
    reset,
  } = useForm<{
    firstName: string;
    lastName: string;
    select: string;
    radio: string | null;
    checkbox: boolean;
    ['checkbox-checked']: boolean;
  }>({
    mode: props.match.params.mode,
    defaultValues: {
      firstName: '',
      lastName: '',
      select: '',
      checkbox: false,
      radio: null,
      'checkbox-checked': true,
    },
  });

  renderCounter++;

  return (
    <form onSubmit={handleSubmit(() => {})}>
      <input
        name="firstName"
        ref={register({ required: true })}
        placeholder="firstName"
      />
      <input
        name="lastName"
        ref={register({ required: true })}
        placeholder="lastName"
      />
      <div id="state">
        {JSON.stringify({
          isSubmitted,
          submitCount,
          isDirty,
          isSubmitting,
          isSubmitSuccessful,
Repository: react-hook-form/react-hook-form
File: src/types/validator.ts (TypeScript)

Code before:

export type ValidateResult = Message | Message[] | boolean | undefined;

export type Validate<TFieldValue> = (
  value: TFieldValue,
) => ValidateResult | Promise<ValidateResult>;

export type RegisterOptions<
  TFieldValues extends FieldValues = FieldValues,
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = Partial<{
  required: Message | ValidationRule<boolean>;
  min: ValidationRule<number | string>;
  max: ValidationRule<number | string>;
  maxLength: ValidationRule<number | string>;
  minLength: ValidationRule<number | string>;
  pattern: ValidationRule<RegExp>;
  validate:
    | Validate<FieldPathValue<TFieldValues, TFieldName>>
    | Record<string, Validate<FieldPathValue<TFieldValues, TFieldName>>>;
  valueAsNumber: boolean;
  valueAsDate: boolean;
  value: FieldPathValue<TFieldValues, TFieldName>;
  setValueAs: (value: any) => any;
  shouldUnregister?: boolean;
  onChange?: (event: any) => void;
  onBlur?: (event: any) => void;
}>;


Review comment (suggestion):
wasn't sure if it should be void or maybe `Promise<boolean | void>`

Code after:

export type ValidateResult = Message | Message[] | boolean | undefined;

export type Validate<TFieldValue> = (
  value: TFieldValue,
) => ValidateResult | Promise<ValidateResult>;

export type RegisterOptions<
  TFieldValues extends FieldValues = FieldValues,
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = Partial<{
  required: Message | ValidationRule<boolean>;
  min: ValidationRule<number | string>;
  max: ValidationRule<number | string>;
  maxLength: ValidationRule<number | string>;
  minLength: ValidationRule<number | string>;
  pattern: ValidationRule<RegExp>;
  validate:
    | Validate<FieldPathValue<TFieldValues, TFieldName>>
    | Record<string, Validate<FieldPathValue<TFieldValues, TFieldName>>>;
  valueAsNumber: boolean;
  valueAsDate: boolean;
  value: FieldPathValue<TFieldValues, TFieldName>;
  setValueAs: (value: any) => any;
  shouldUnregister?: boolean;
  onChange?: (event: any) => void;
  onBlur?: (event: any) => void;
  disabled: boolean;
  deps: InternalFieldName[];
}>;