fix(modal-repeater-table): 품목 추가 시 UI 즉시 반영되지 않는 버그 수정
- value 상수를 localValue useState로 변경하여 내부 상태 관리 - useEffect로 외부 값(formData, propValue) 변경 시 동기화 - handleChange에서 setLocalValue 호출하여 즉각적인 UI 업데이트 - RepeaterTable, ItemSelectionModal 등 모든 참조를 localValue로 변경
This commit is contained in:
@@ -193,7 +193,18 @@ export function ModalRepeaterTableComponent({
|
||||
|
||||
// ✅ value는 formData[columnName] 우선, 없으면 prop 사용
|
||||
const columnName = component?.columnName;
|
||||
const value = (columnName && formData?.[columnName]) || componentConfig?.value || propValue || [];
|
||||
const externalValue = (columnName && formData?.[columnName]) || componentConfig?.value || propValue || [];
|
||||
|
||||
// 🆕 내부 상태로 데이터 관리 (즉시 UI 반영을 위해)
|
||||
const [localValue, setLocalValue] = useState<any[]>(externalValue);
|
||||
|
||||
// 🆕 외부 값(formData, propValue) 변경 시 내부 상태 동기화
|
||||
useEffect(() => {
|
||||
// 외부 값이 변경되었고, 내부 값과 다른 경우에만 동기화
|
||||
if (JSON.stringify(externalValue) !== JSON.stringify(localValue)) {
|
||||
setLocalValue(externalValue);
|
||||
}
|
||||
}, [externalValue]);
|
||||
|
||||
// ✅ onChange 래퍼 (기존 onChange 콜백 + onFormDataChange 호출 + 납기일 일괄 적용)
|
||||
const handleChange = (newData: any[]) => {
|
||||
@@ -249,6 +260,9 @@ export function ModalRepeaterTableComponent({
|
||||
}
|
||||
}
|
||||
|
||||
// 🆕 내부 상태 즉시 업데이트 (UI 즉시 반영) - 일괄 적용된 데이터로 업데이트
|
||||
setLocalValue(processedData);
|
||||
|
||||
// 기존 onChange 콜백 호출 (호환성)
|
||||
const externalOnChange = componentConfig?.onChange || propOnChange;
|
||||
if (externalOnChange) {
|
||||
@@ -321,7 +335,7 @@ export function ModalRepeaterTableComponent({
|
||||
const handleSaveRequest = async (event: Event) => {
|
||||
const componentKey = columnName || component?.id || "modal_repeater_data";
|
||||
|
||||
if (value.length === 0) {
|
||||
if (localValue.length === 0) {
|
||||
console.warn("⚠️ [ModalRepeaterTable] 저장할 데이터 없음");
|
||||
return;
|
||||
}
|
||||
@@ -332,7 +346,7 @@ export function ModalRepeaterTableComponent({
|
||||
.filter(col => col.mapping?.type === "source" && col.mapping?.sourceField)
|
||||
.map(col => col.field);
|
||||
|
||||
const filteredData = value.map((item: any) => {
|
||||
const filteredData = localValue.map((item: any) => {
|
||||
const filtered: Record<string, any> = {};
|
||||
|
||||
Object.keys(item).forEach((key) => {
|
||||
@@ -389,16 +403,16 @@ export function ModalRepeaterTableComponent({
|
||||
return () => {
|
||||
window.removeEventListener("beforeFormSave", handleSaveRequest as EventListener);
|
||||
};
|
||||
}, [value, columnName, component?.id, onFormDataChange, targetTable]);
|
||||
}, [localValue, columnName, component?.id, onFormDataChange, targetTable]);
|
||||
|
||||
const { calculateRow, calculateAll } = useCalculation(calculationRules);
|
||||
|
||||
// 초기 데이터에 계산 필드 적용
|
||||
useEffect(() => {
|
||||
if (value.length > 0 && calculationRules.length > 0) {
|
||||
const calculated = calculateAll(value);
|
||||
if (localValue.length > 0 && calculationRules.length > 0) {
|
||||
const calculated = calculateAll(localValue);
|
||||
// 값이 실제로 변경된 경우만 업데이트
|
||||
if (JSON.stringify(calculated) !== JSON.stringify(value)) {
|
||||
if (JSON.stringify(calculated) !== JSON.stringify(localValue)) {
|
||||
handleChange(calculated);
|
||||
}
|
||||
}
|
||||
@@ -506,7 +520,7 @@ export function ModalRepeaterTableComponent({
|
||||
const calculatedItems = calculateAll(mappedItems);
|
||||
|
||||
// 기존 데이터에 추가
|
||||
const newData = [...value, ...calculatedItems];
|
||||
const newData = [...localValue, ...calculatedItems];
|
||||
console.log("✅ 최종 데이터:", newData.length, "개 항목");
|
||||
|
||||
// ✅ 통합 onChange 호출 (formData 반영 포함)
|
||||
@@ -518,7 +532,7 @@ export function ModalRepeaterTableComponent({
|
||||
const calculatedRow = calculateRow(newRow);
|
||||
|
||||
// 데이터 업데이트
|
||||
const newData = [...value];
|
||||
const newData = [...localValue];
|
||||
newData[index] = calculatedRow;
|
||||
|
||||
// ✅ 통합 onChange 호출 (formData 반영 포함)
|
||||
@@ -526,7 +540,7 @@ export function ModalRepeaterTableComponent({
|
||||
};
|
||||
|
||||
const handleRowDelete = (index: number) => {
|
||||
const newData = value.filter((_, i) => i !== index);
|
||||
const newData = localValue.filter((_, i) => i !== index);
|
||||
|
||||
// ✅ 통합 onChange 호출 (formData 반영 포함)
|
||||
handleChange(newData);
|
||||
@@ -543,7 +557,7 @@ export function ModalRepeaterTableComponent({
|
||||
{/* 추가 버튼 */}
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{value.length > 0 && `${value.length}개 항목`}
|
||||
{localValue.length > 0 && `${localValue.length}개 항목`}
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setModalOpen(true)}
|
||||
@@ -557,7 +571,7 @@ export function ModalRepeaterTableComponent({
|
||||
{/* Repeater 테이블 */}
|
||||
<RepeaterTable
|
||||
columns={columns}
|
||||
data={value}
|
||||
data={localValue}
|
||||
onDataChange={handleChange}
|
||||
onRowChange={handleRowChange}
|
||||
onRowDelete={handleRowDelete}
|
||||
@@ -573,7 +587,7 @@ export function ModalRepeaterTableComponent({
|
||||
multiSelect={multiSelect}
|
||||
filterCondition={filterCondition}
|
||||
modalTitle={modalTitle}
|
||||
alreadySelected={value}
|
||||
alreadySelected={localValue}
|
||||
uniqueField={uniqueField}
|
||||
onSelect={handleAddItems}
|
||||
columnLabels={columnLabels}
|
||||
|
||||
Reference in New Issue
Block a user