this is my component. i don’t know why the moment i reload the page it’ll always give me infinite loop issue. it’ll throw the error the moment i go the page. i can’t even fill in anything inside the form field.
'use client';
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import Accordion from '@/components/common/accordion';
import { ProductDetails } from '@/components/product/productDetails';
import { ProductBenefit } from '@/components/product/productBenefit';
import { ProductQuestion } from '@/components/product/productQuestion';
import { PORDUCT_BENEFIT_DATA, PORDUCT_DETAILS_DATA, PORDUCT_QUESTION_DATA, ProductBenefitData, ProductDetailsData, ProductQuestionData } from '@/model/product.type';
import CommonButton from '../common/form-element/commonButton';
import { FormButtonType } from '@/model/form.type';
interface ProductFormProps {
productCode: string;
onBack: () => void;
}
const ProductForm: React.FC<ProductFormProps> = ({ productCode, onBack }) => {
const { t } = useTranslation();
const [productDetailsData, setProductDetailsData] = useState<ProductDetailsData>(PORDUCT_DETAILS_DATA);
const [productBenefitData, setProductBenefitData] = useState<ProductBenefitData>(PORDUCT_BENEFIT_DATA);
const [productQuestionData, setProductQuestionData] = useState<ProductQuestionData>(PORDUCT_QUESTION_DATA);
const [isValid, setIsValid] = useState(false);
const handleProductDetailsChange = (formData: ProductDetailsData) => {
setProductDetailsData(formData);
};
const handleProductBenefitChange = (formData: ProductBenefitData) => {
setProductBenefitData(formData);
};
const handleProductQuestionChange = (formData: ProductQuestionData) => {
setProductQuestionData(formData);
};
const handleValidationChange = (isValid: boolean) => {
setIsValid(isValid);
};
const handleSubmit = () => {
const mergedData = {
...productDetailsData,
...productQuestionData,
...productBenefitData,
};
const existingProductsJSON = localStorage.getItem('ProductList');
const existingProducts = existingProductsJSON ? JSON.parse(existingProductsJSON) : [];
const updatedProducts = [...existingProducts, mergedData];
localStorage.setItem('ProductList', JSON.stringify(updatedProducts));
onBack();
};
return (
<div className="container w-full">
<div className="bg-white">
<div className="h-full container px-0 mx-auto mb-4">
<div className="w-full">
<Accordion title={t('Product.section.details')} isOpen={true}>
<ProductDetails
onChange={handleProductDetailsChange}
productFormData={productDetailsData}
onValidationChange={handleValidationChange}
isEdit={false}
/>
</Accordion>
<Accordion title={t('Product.section.question')}>
<ProductQuestion
onChange={handleProductQuestionChange}
productQuestionData={productQuestionData}
onValidationChange={handleValidationChange}
isEdit={false}
/>
</Accordion>
<Accordion title={t('Product.section.benefit')}>
<ProductBenefit
onChange={handleProductBenefitChange}
productBenefitData={productBenefitData}
onValidationChange={handleValidationChange}
isEdit={false}
/>
</Accordion>
<div className="flex justify-end mt-4">
<div className="w-40">
<CommonButton
buttonType={FormButtonType.PRIMARY}
buttonText={t('Common.submit')}
isSubmit={false}
onChange={handleSubmit}
isDisabled={!isValid}
/>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default ProductForm;
'use client';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import TextInput from '../common/form-element/textInput';
import DropDown from '../common/form-element/dropDown';
import RadioBoxes from '../common/form-element/radioBoxes';
import CommonForm from '../common/commonForm';
import { PRODUCT_DETAILS_SCHEMA, ProductDetailsData } from '@/model/product.type';
import { FormAlignment, FormField, LabelType, LayoutType } from '@/model/form.type';
import { BOOLEAN_YES_OR_NO_OPTIONS, ENTITY, PRODUCT_TYPE } from '@/model/common.type';
type ProductDetailsProps = {
onChange: (productDetailsData: ProductDetailsData) => void;
productDetailsData: ProductDetailsData;
onValidationChange: (isValid: boolean) => void;
isEdit: boolean;
};
export const ProductDetails: React.FC<ProductDetailsProps> = ({ onChange, productDetailsData, onValidationChange, isEdit }) => {
const { t } = useTranslation();
const [formData, setFormData] = useState(productDetailsData);
const [isValid, setIsValid] = useState(false);
useEffect(() => {
onChange(formData);
}, [formData]);
useEffect(() => {
onValidationChange(isValid);
}, [isValid]);
const fields: FormField<any>[] = [
{
name: 'ProductCode',
label: 'Product.code',
component: TextInput,
layout: LayoutType.HALF,
isDisabled: isEdit,
isRequired: true,
labelType: LabelType.LABEL,
},
{
name: 'Entity',
label: 'Product.entity',
component: DropDown,
layout: LayoutType.HALF,
options: ENTITY,
isDisabled: isEdit,
isRequired: true,
labelType: LabelType.LABEL,
},
{
name: 'Version',
label: 'Product.version',
component: TextInput,
layout: LayoutType.HALF,
isDisabled: false,
isRequired: true,
labelType: LabelType.LABEL,
},
{
name: 'PlanType',
label: 'Product.planType',
component: DropDown,
layout: LayoutType.HALF,
options: PRODUCT_TYPE,
isDisabled: false,
isRequired: false,
labelType: LabelType.LABEL,
},
{
name: 'ProductNameENG',
label: 'Product.nameENG',
component: TextInput,
layout: LayoutType.FULL,
isDisabled: false,
isRequired: true,
labelType: LabelType.LABEL,
},
{
name: 'ProductNameBMY',
label: 'Product.nameBMY',
component: TextInput,
layout: LayoutType.FULL,
isDisabled: false,
isRequired: true,
labelType: LabelType.LABEL,
},
{
name: 'AdvantageProgram',
label: 'Product.advantageProgram',
component: RadioBoxes,
layout: LayoutType.HALF,
options: BOOLEAN_YES_OR_NO_OPTIONS,
isDisabled: false,
isRequired: true,
labelType: LabelType.LABEL
},
{
name: 'IsJuvenile',
label: 'Product.isJuvenile',
component: RadioBoxes,
layout: LayoutType.HALF,
options: BOOLEAN_YES_OR_NO_OPTIONS,
isDisabled: false,
isRequired: true,
labelType: LabelType.LABEL
},
];
const handleSubmit = (data: ProductDetailsData, isFormValid?: boolean) => {
setFormData(data);
setIsValid(isFormValid ?? false);
};
return (
<CommonForm
schema={PRODUCT_DETAILS_SCHEMA}
fields={fields}
defaultFormData={formData}
formButtons={[]}
onSubmit={handleSubmit}
formAlignment={FormAlignment.HORIZONTAL_THREE_QUARTERS}
/>
);
};
Im expect i wont get the infinite loop issue when i go the form page. but now it keeps giving me that.
Fatin Syafiqah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
99% of all infinite rendering in React is due to useEffect.
you wrote
onChange(formData);
}, [formData]);
There is a high possibility of problems occurring in that area. When the form element changes, the data received from the parent element changes to onChnage and is passed back to props, which is likely to be a problem.