I am unable to remove the deleted item from arrayFields
, even though I am calling the removeArrayField (remove) method with correct arguments. My state does not change even after calling the remove method
executive-form.tsx
import { getRadioButtonYesNoOptions } from '@company-onboarding/company-onboarding.data';
import { getUpdatedPercentageFieldsBasedOnEntityType } from '@company-onboarding/company-onboarding.utils';
import { useUpsertExecutives } from '@company-onboarding/hooks/useUpsertExecutives';
import { getSumOfAllExecutiveEquities } from '@components/onboarding/onboarding-form.helpers';
import { PayloadType } from '@components/onboarding/onboarding-form.utils';
import {
BlockSeparator,
PrimaryButton,
PrimaryOptionsInput,
ShadowCover,
} from '@paf-ui-components-library';
import { useEntriesToData, useToast } from '@paf-ui-components-library/hooks';
import {
BusinessEntitiesType,
BusinessExecutiveType,
CompanyDueDiligenceDto,
DirectorInformationInputDto,
IndividualBeneficialOwnerInputDto,
LegalEntityBeneficialOwnerInputDto,
ManagementInformationInputDto,
OwnerRelationshipToBusiness,
} from '@utils/interfaces-graphql';
import { useStoreActions } from '@utils/store';
import React, { useEffect } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { ExecutiveDetails } from './ExecutiveDetails';
export type SubmitExecutiveDataType = {
individualBeneficialOwners?: IndividualBeneficialOwnerInputDto[];
legalEntityBeneficialOwners?: LegalEntityBeneficialOwnerInputDto[];
managementExecutives?: ManagementInformationInputDto[];
boardDirectors?: DirectorInformationInputDto[];
indexToUpdate?: number;
};
interface IProps {
executiveType: BusinessExecutiveType;
prefix: string;
onUpdateExecutive: (data: SubmitExecutiveDataType) => void;
shouldPrefill: boolean;
}
export const BusinessExecutiveForm: React.FC<IProps> = ({
executiveType,
onUpdateExecutive,
prefix,
shouldPrefill,
}) => {
const { toast } = useToast();
const { t } = useTranslation();
const radioButtonOptions = getRadioButtonYesNoOptions();
const { updateCustomerData } = useStoreActions((actions) => actions);
const { OWNER_RELATIONSHIP_TO_BUSINESS } = useEntriesToData({
OwnerRelationshipToBusiness,
});
const { control, getValues, resetField, setValue, watch } = useFormContext();
const { handleDeleteExecutivesById } = useUpsertExecutives(executiveType);
const businessEntityType = watch('companyProfile.entityType') as BusinessEntitiesType;
const {
append: appendArrayField,
fields: arrayFields,
remove: removeArrayField,
} = useFieldArray({ control, name: prefix });
const isBeneficialOwner = [
BusinessExecutiveType.IndividualBeneficialOwner,
BusinessExecutiveType.LegalEntityBeneficialOwner,
].includes(executiveType);
const handleAddExecutive = () => {
if (isBeneficialOwner) {
const { totalEquity } = getSumOfAllExecutiveEquities(getValues() as CompanyDueDiligenceDto);
if (totalEquity >= 100) {
toast({
message: t('errors.existing_owners_already_owns_100_percent_equity'),
type: 'error',
});
return;
}
}
appendArrayField({});
};
const handleRemoveExecutive = async (index: number) => {
let shouldRemove = true;
const executiveId = watch(prefix)?.[index]?._id;
if (executiveId) {
const finalResponse = await handleDeleteExecutivesById({
executiveId,
executiveType,
});
if (finalResponse) {
updateCustomerData({
type: PayloadType.COMPANY_DUE_DILIGENCE,
data: finalResponse,
});
console.log({
finalResponse,
});
} else {
// set should remove false if failed to delete
shouldRemove = false;
}
}
// If its last executive and is not beneficial owner then reset fields instead of removing it
if (shouldRemove && (arrayFields.length > 1 || isBeneficialOwner)) {
console.log({
index,
arrayFields,
});
// setTimeout(() => {
// removeArrayField(index);
// }, 100);
removeArrayField(index);
} else {
resetField(prefix, { defaultValue: [{}] });
}
// Debugging State
console.log('After removal or reset:', {
arrayFields,
});
};
useEffect(() => {
if (shouldPrefill) {
// TODO: To handle the case when filling different percentage field
// const individualBeneficialOwners = watch('selectedMeritId.individualBeneficialOwners') || [];
// const individualOwner = individualBeneficialOwners[0] || {};
const executivePrefillingData = getUpdatedPercentageFieldsBasedOnEntityType(
watch(`selectedMeritId.${prefix}`) || [{}],
businessEntityType,
);
if (executiveType === BusinessExecutiveType.IndividualBeneficialOwner) {
setValue('isLegalOrIndividualOwnersExist', 'YES');
}
setValue(prefix, executivePrefillingData);
}
}, []);
console.log({
length: arrayFields.length,
arrayFields,
});
return (
<>
{arrayFields.map((field, index) => (
<ExecutiveDetails
executiveType={executiveType}
headerTitle={t(`${executiveType.toLowerCase()}.array_field_title`, {
count: index + 1 + field.id,
})}
isHideDeleteButton={index === 0 && !isBeneficialOwner && !watch(prefix)?.[0]?._id}
key={field.id}
onRemove={() => handleRemoveExecutive(index)}
onUpdate={() => {
onUpdateExecutive({
[prefix]: watch(prefix) || [],
indexToUpdate: index,
});
}}
prefix={`${prefix}.${index}`}
>
{/* Business relationship is only for Individual Beneficial Owners */}
{executiveType === BusinessExecutiveType.IndividualBeneficialOwner && (
<ShadowCover
description={t(`${executiveType.toLowerCase()}.relation_to_business_description`)}
title={t(`${executiveType.toLowerCase()}.relation_to_business`)}
>
<PrimaryOptionsInput
data={OWNER_RELATIONSHIP_TO_BUSINESS.filter(
({ value }) => value !== OwnerRelationshipToBusiness.None,
)}
name={`${prefix}.${index}.relationToBusiness`}
type="checkbox"
/>
</ShadowCover>
)}
{/* Only for Board directors */}
{executiveType === BusinessExecutiveType.BoardDirector && (
<PrimaryOptionsInput
className="grid-1x2"
data={radioButtonOptions}
heading={t(`${executiveType.toLowerCase()}.is_director_also_manager`)}
name={`${prefix}.${index}.isDirectorManager`}
type="radio"
/>
)}
</ExecutiveDetails>
))}
<BlockSeparator>
<ShadowCover>
<PrimaryButton
className="add-array-field-button"
onClick={handleAddExecutive}
type="button"
variantsStyle={['primary-button-accent', 'primary-button-transparent']}
>
{t(`${executiveType.toLowerCase()}.add_executive_button_text`)}
</PrimaryButton>
</ShadowCover>
</BlockSeparator>
</>
);
};
The issue lies in handleRemoveExecutive
method :-
const handleRemoveExecutive = async (index: number) => {
let shouldRemove = true;
const executiveId = watch(prefix)?.[index]?._id;
if (executiveId) {
const finalResponse = await handleDeleteExecutivesById({
executiveId,
executiveType,
});
if (finalResponse) {
updateCustomerData({
type: PayloadType.COMPANY_DUE_DILIGENCE,
data: finalResponse,
});
console.log({
finalResponse,
});
} else {
// set should remove false if failed to delete
shouldRemove = false;
}
}
// If its last executive and is not beneficial owner then reset fields instead of removing it
if (shouldRemove && (arrayFields.length > 1 || isBeneficialOwner)) {
console.log({
index,
arrayFields,
});
// this successfully the deleted item from the arrayFields
// setTimeout(() => {
// removeArrayField(index);
// }, 100);
removeArrayField(index);
} else {
resetField(prefix, { defaultValue: [{}] });
}
// Debugging State
console.log('After removal or reset:', {
arrayFields,
});
};
removeArrayField(index)
does not removes the deleted item from arrayFields
but if I were to use this method in a setTimeOut, the deleted item also gets removed successfully from arrayFields