diff --git a/src/__tests__/useForm/formState.test.tsx b/src/__tests__/useForm/formState.test.tsx
index 2f4724fccca..f0db9b9d099 100644
--- a/src/__tests__/useForm/formState.test.tsx
+++ b/src/__tests__/useForm/formState.test.tsx
@@ -10,6 +10,7 @@ import { act, renderHook } from '@testing-library/react-hooks';
import { VALIDATION_MODE } from '../../constants';
import { Controller } from '../../controller';
+import { useFieldArray } from '../../useFieldArray';
import { useForm } from '../../useForm';
describe('formState', () => {
@@ -260,4 +261,154 @@ describe('formState', () => {
screen.getByText('isSubmitted');
screen.getByText('isNotSubmitSuccessful');
});
+
+ it('should update correct isValid formState with dynamic fields', async () => {
+ const Component = () => {
+ const {
+ register,
+ control,
+ formState: { isValid },
+ } = useForm<{
+ list: {
+ firstName: string;
+ lastName: string;
+ }[];
+ test: string;
+ test1: string;
+ test2: string;
+ test3: string;
+ }>({
+ mode: 'onChange',
+ });
+ const { append, fields } = useFieldArray({
+ control,
+ name: 'list',
+ });
+
+ return (
+
+ );
+ };
+
+ render();
+
+ screen.getByText('inValid');
+
+ fireEvent.change(screen.getByPlaceholderText('test'), {
+ target: { value: '1' },
+ });
+ fireEvent.change(screen.getByPlaceholderText('test1'), {
+ target: { value: '1' },
+ });
+
+ await waitFor(async () => {
+ screen.getByText('valid');
+ });
+
+ fireEvent.click(screen.getByRole('button'));
+
+ await waitFor(async () => {
+ screen.getByText('inValid');
+ });
+
+ fireEvent.change(screen.getByPlaceholderText('list.0.firstName'), {
+ target: { value: '1' },
+ });
+ fireEvent.change(screen.getByPlaceholderText('list.0.lastName'), {
+ target: { value: '1' },
+ });
+
+ await waitFor(async () => {
+ screen.getByText('valid');
+ });
+
+ fireEvent.change(screen.getByPlaceholderText('list.0.lastName'), {
+ target: { value: '' },
+ });
+
+ await waitFor(async () => {
+ screen.getByText('inValid');
+ });
+
+ fireEvent.change(screen.getByPlaceholderText('list.0.lastName'), {
+ target: { value: '1' },
+ });
+
+ await waitFor(async () => {
+ screen.getByText('valid');
+ });
+
+ fireEvent.change(screen.getByPlaceholderText('list.0.firstName'), {
+ target: { value: '' },
+ });
+
+ await waitFor(async () => {
+ screen.getByText('inValid');
+ });
+
+ fireEvent.change(screen.getByPlaceholderText('list.0.firstName'), {
+ target: { value: '1' },
+ });
+
+ await waitFor(async () => {
+ screen.getByText('valid');
+ });
+ });
});
diff --git a/src/useForm.ts b/src/useForm.ts
index 0b879e47d13..60667c192e3 100644
--- a/src/useForm.ts
+++ b/src/useForm.ts
@@ -170,10 +170,13 @@ export function useForm<
contextRef.current = context;
resolverRef.current = resolver;
- const getIsValid = () =>
- (formStateRef.current.isValid =
+ const getIsValid = () => {
+ formStateRef.current.isValid =
deepEqual(validFieldsRef.current, fieldsWithValidationRef.current) &&
- isEmptyObject(formStateRef.current.errors));
+ isEmptyObject(formStateRef.current.errors);
+
+ return formStateRef.current.isValid;
+ };
const shouldRenderBaseOnError = React.useCallback(
(