fix(frontend): 일정 추가/수정 페이지 useEffect → useQuery 변경

- React 18 Strict Mode 중복 요청 방지
- members, categories를 useQuery로 전환
- 수정 모드 일정 로드는 useEffect 유지 (폼 상태 초기화 필요)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-01-21 14:26:59 +09:00
parent e3278c81de
commit 84113a8c48

View file

@ -1,5 +1,6 @@
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from "react";
import { useNavigate, Link, useParams } from "react-router-dom"; import { useNavigate, Link, useParams } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { motion, AnimatePresence } from "framer-motion"; import { motion, AnimatePresence } from "framer-motion";
import { formatDate } from "../../../utils/date"; import { formatDate } from "../../../utils/date";
import { import {
@ -42,7 +43,6 @@ function AdminScheduleForm() {
const { toast, setToast } = useToast(); const { toast, setToast } = useToast();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [members, setMembers] = useState([]);
// (/ ) // (/ )
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -77,8 +77,22 @@ function AdminScheduleForm() {
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [deleteTargetIndex, setDeleteTargetIndex] = useState(null); const [deleteTargetIndex, setDeleteTargetIndex] = useState(null);
// (API ) //
const [categories, setCategories] = useState([]); const { data: membersData = [] } = useQuery({
queryKey: ["members"],
queryFn: getMembers,
enabled: isAuthenticated,
staleTime: 5 * 60 * 1000,
});
const members = membersData.filter((m) => !m.is_former);
//
const { data: categories = [] } = useQuery({
queryKey: ["admin", "categories"],
queryFn: categoriesApi.getCategories,
enabled: isAuthenticated,
staleTime: 5 * 60 * 1000,
});
// //
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
@ -132,28 +146,16 @@ function AdminScheduleForm() {
return days[date.getDay()]; return days[date.getDay()];
}; };
// //
const fetchCategories = async () => {
try {
const data = await categoriesApi.getCategories();
setCategories(data);
//
if (data.length > 0 && !formData.category) {
setFormData((prev) => ({ ...prev, category: data[0].id }));
}
} catch (error) {
console.error("카테고리 로드 오류:", error);
}
};
useEffect(() => { useEffect(() => {
if (!isAuthenticated) return; if (categories.length > 0 && !formData.category && !isEditMode) {
setFormData((prev) => ({ ...prev, category: categories[0].id }));
}
}, [categories, isEditMode]);
fetchMembers(); //
fetchCategories(); useEffect(() => {
if (isAuthenticated && isEditMode && id) {
//
if (isEditMode && id) {
fetchSchedule(); fetchSchedule();
} }
}, [isAuthenticated, isEditMode, id]); }, [isAuthenticated, isEditMode, id]);
@ -223,15 +225,6 @@ function AdminScheduleForm() {
} }
}; };
const fetchMembers = async () => {
try {
const data = await getMembers();
setMembers(data.filter((m) => !m.is_former));
} catch (error) {
console.error("멤버 로드 오류:", error);
}
};
// //
const toggleMember = (memberId) => { const toggleMember = (memberId) => {
const newMembers = formData.members.includes(memberId) const newMembers = formData.members.includes(memberId)