From 9ff6f3a35d98a818f980fb727623cca6e64cac22 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Thu, 5 Mar 2026 15:59:32 +0700 Subject: [PATCH] refactor(FE): Refactor form components to improve state handling --- .../expense/form/ExpenseKandangsTable.tsx | 54 ++++++++++++------- .../expense/form/ExpenseRealizationForm.tsx | 8 +-- .../pages/expense/form/ExpenseRequestForm.tsx | 23 ++++---- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/components/pages/expense/form/ExpenseKandangsTable.tsx b/src/components/pages/expense/form/ExpenseKandangsTable.tsx index 5c60ae1e..bc779417 100644 --- a/src/components/pages/expense/form/ExpenseKandangsTable.tsx +++ b/src/components/pages/expense/form/ExpenseKandangsTable.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import useSWR from 'swr'; import { Icon } from '@iconify/react'; @@ -75,6 +75,12 @@ const ExpenseKandangsTable = ({ .filter((id): id is number => id !== undefined) ) ); + const rowSelectionRef = useRef(rowSelection); + const prevRowSelectionRef = useRef>({}); + + useEffect(() => { + rowSelectionRef.current = rowSelection; + }, [rowSelection]); const kandangsColumns: ColumnDef[] = [ { @@ -133,33 +139,43 @@ const ExpenseKandangsTable = ({ useEffect(() => { setOpen(isResponseSuccess(kandangs) ? kandangs.data.length > 0 : false); - }, [kandangs, isResponseSuccess]); + }, [kandangs]); useEffect(() => { - if (Object.keys(rowSelection).length !== 0 && isResponseSuccess(kandangs)) { - const formattedSelectedKandangs = Object.keys(rowSelection).map( - (item) => { - const selectedKandang = kandangs.data.find( - (kandang) => kandang.id === parseInt(item) - ); + const currentKeys = Object.keys(rowSelection).sort().join(','); + const prevKeys = Object.keys(prevRowSelectionRef.current).sort().join(','); - return { - id: parseInt(item), - name: selectedKandang?.name ?? 'Kandang tidak ditemukan!', - }; - } - ); + if (currentKeys !== prevKeys) { + prevRowSelectionRef.current = { ...rowSelection }; - onChange(formattedSelectedKandangs); - } else { - onChange([]); + if ( + Object.keys(rowSelection).length !== 0 && + isResponseSuccess(kandangs) + ) { + const formattedSelectedKandangs = Object.keys(rowSelection).map( + (item) => { + const selectedKandang = kandangs.data.find( + (kandang) => kandang.id === parseInt(item) + ); + + return { + id: parseInt(item), + name: selectedKandang?.name ?? 'Kandang tidak ditemukan!', + }; + } + ); + + onChange(formattedSelectedKandangs); + } else if (Object.keys(rowSelection).length === 0) { + onChange([]); + } } - }, [rowSelection]); + }, [rowSelection, kandangs, onChange]); useEffect(() => { if ( selectedKandangs.length === 0 && - Object.keys(rowSelection).length !== 0 + Object.keys(rowSelectionRef.current).length !== 0 ) { setRowSelection({}); } diff --git a/src/components/pages/expense/form/ExpenseRealizationForm.tsx b/src/components/pages/expense/form/ExpenseRealizationForm.tsx index acc0a393..e9720d0b 100644 --- a/src/components/pages/expense/form/ExpenseRealizationForm.tsx +++ b/src/components/pages/expense/form/ExpenseRealizationForm.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useState } from 'react'; import { useRouter } from 'next/navigation'; import { useFormik } from 'formik'; import toast from 'react-hot-toast'; @@ -90,6 +90,7 @@ const ExpenseRealizationForm = ({ const formik = useFormik({ initialValues: getExpenseRealizationFormInitialValues(initialValues), + enableReinitialize: true, validationSchema: type === 'edit' ? UpdateExpenseRealizationFormSchema @@ -143,7 +144,6 @@ const ExpenseRealizationForm = ({ }, }); - const { setValues: formikSetValues } = formik; const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik); const { @@ -254,10 +254,6 @@ const ExpenseRealizationForm = ({ formik.setFieldValue('documents', newRequestDocuments); }; - useEffect(() => { - formikSetValues(getExpenseRealizationFormInitialValues(initialValues)); - }, [formikSetValues, getExpenseRealizationFormInitialValues, initialValues]); - return (
diff --git a/src/components/pages/expense/form/ExpenseRequestForm.tsx b/src/components/pages/expense/form/ExpenseRequestForm.tsx index 733204d9..adc825c2 100644 --- a/src/components/pages/expense/form/ExpenseRequestForm.tsx +++ b/src/components/pages/expense/form/ExpenseRequestForm.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useState } from 'react'; import { useRouter } from 'next/navigation'; import { useFormik } from 'formik'; import { toast } from 'react-hot-toast'; @@ -102,6 +102,7 @@ const ExpenseRequestForm = ({ const formik = useFormik({ initialValues: getExpenseFormInitialValues(initialValues), + enableReinitialize: true, validationSchema: type === 'edit' ? UpdateExpenseRequestFormSchema @@ -171,7 +172,7 @@ const ExpenseRequestForm = ({ }, }); - const { setValues: formikSetValues } = formik; + const { setFieldValue, setFieldTouched } = formik; const { setInputValue: setLocationInputValue, @@ -186,8 +187,8 @@ const ExpenseRequestForm = ({ } = useSelect(SupplierApi.basePath, 'id', 'name'); const categoryChangeHandler = (val: OptionType | OptionType[] | null) => { - formik.setFieldTouched('category', true); - formik.setFieldValue('category', val); + setFieldTouched('category', true); + setFieldValue('category', val); }; const locationChangeHandler = useCallback( @@ -195,12 +196,12 @@ const ExpenseRequestForm = ({ const location = val as OptionType | null; const locationId = location ? Number(location.value) : 0; - formik.setFieldTouched('location', true); - formik.setFieldValue('location', location); - formik.setFieldTouched('location_id', true); - formik.setFieldValue('location_id', locationId); + setFieldTouched('location', true); + setFieldValue('location', location); + setFieldTouched('location_id', true); + setFieldValue('location_id', locationId); }, - [] + [setFieldTouched, setFieldValue] ); const kandangsChangeHandler = ( @@ -343,10 +344,6 @@ const ExpenseRequestForm = ({ formik.handleSubmit(e); }; - useEffect(() => { - formikSetValues(getExpenseFormInitialValues(initialValues)); - }, [formikSetValues, getExpenseFormInitialValues, initialValues]); - return ( <>