Skip to content

Conversation

@cywin1018
Copy link
Contributor

@cywin1018 cywin1018 commented Sep 4, 2025

🚀 풀 리퀘스트 제안

  • 기능 추가

✈️ 관련 이슈

📋 작업 내용

커뮤니티 왼쪽 페이지 api 연결 작업

📸 스크린샷 (선택 사항)

image

📄 기타

Summary by CodeRabbit

  • 신규 기능
    • 커뮤니티 페이지에 직무 선택 드롭다운 추가: 서버에서 초기값을 받아 자동 설정되고 직접 선택 가능해졌습니다.
    • 선택한 직무에 맞는 HOT 할 일 목록이 동적으로 표시됩니다(순위, 이미지, 설명, D-Day, 저장 수 등 반영).
    • 로그인 시 권한 있는 커뮤니티 데이터(예: 개인화된 목록)를 안전하게 불러옵니다.
    • 직무 목록과 조회용 검색 기능이 추가되어 전체보기 버튼이 선택된 직무로 이동합니다.

@cywin1018 cywin1018 requested a review from Chasyuss September 4, 2025 13:36
@coderabbitai
Copy link

coderabbitai bot commented Sep 4, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

커뮤니티 페이지를 데이터 기반으로 전환했다. 직무 선택 드롭다운과 Zustand 전역 상태를 도입했고, 두 가지 React Query 훅을 추가해 직무 목록(/v1/community/job)과 선택 직무의 HOT 할 일(/v1/community/todos/popular)을 조회한다. Community 페이지는 해당 데이터로 UI를 동적으로 렌더링한다. 전역 스토어는 setSelectedJob({ name, id }) 형태로 변경되어 직무명과 id를 함께 보관한다.

Changes

Cohort / File(s) Change summary
React Query 훅 추가
src/hook/community/query/useGetCommunityQuery.ts, src/hook/community/query/useGetHotPopularQuery.ts
커뮤니티 직무 목록과 HOT 할 일 조회 훅 추가. 클라이언트에서 window/localStorage 가드로 토큰 판별, 쿼리키에 로그인 상태/선택 직무 반영, GET 요청에 필요 시 Authorization: Bearer <token> 헤더 포함. 응답 가드, staleTime: 5분, refetchOnWindowFocus: false. HotPopularItem 타입 추가.
커뮤니티 페이지 연동
src/pages/community/Community.tsx
정적 UI를 드롭다운+쿼리 데이터 기반으로 교체. selectedJobName을 헤더에 반영하고 useGetHotPopularQuery로 받아온 인기 할 일 목록으로 리스트 렌더링. 전체보기 네비게이션에 findJobIdByName(selectedJobName) 사용.
드롭다운 컴포넌트
src/pages/community/components/CommunityDropdown.tsx
제네릭 드롭다운 추가. 초기값을 useGetCommunityQuery API 응답으로 유도, 외부 value 동기화, 사용자 선택시 onSelect 호출 및 전역 상태 setSelectedJob 업데이트. 외부 클릭 닫기, 스크롤 처리 등 UI 동작 포함.
전역 상태(Zustand) 변경
src/store/useCommunityStore.ts
스토어 구조 변경: selectedJobName: string, `selectedJobId: number
정적 데이터 및 유틸
src/utils/data/community/jobs.ts
한국어 직무 목록(jobs)과 jobNames 배열, findJobIdByName(name) 유틸 추가(기본 export jobNames).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 사용자
  participant Page as Community.tsx
  participant Dropdown as CommunityDropdown
  participant Store as useCommunityStore
  participant HookJobs as useGetCommunityQuery
  participant HookHot as useGetHotPopularQuery
  participant API as Backend API

  User->>Page: 페이지 진입
  Page->>Dropdown: 드롭다운 렌더
  activate Dropdown
  Dropdown->>HookJobs: GET /v1/community/job 요청
  HookJobs->>API: GET /v1/community/job (Bearer 토큰 포함 가능)
  API-->>HookJobs: 직무 목록 응답
  HookJobs-->>Dropdown: 직무 데이터 반환
  Dropdown->>Store: setSelectedJob({ name, id })로 초기 선택 설정
  deactivate Dropdown

  Note over Page,HookHot: 선택 직무명 변경 시
  Page->>Store: selectedJobName 구독
  Store-->>Page: 선택된 직무명
  Page->>HookHot: GET /v1/community/todos/popular?jobName=...
  HookHot->>API: 인기 할 일 요청
  API-->>HookHot: 인기 할 일 배열 응답
  HookHot-->>Page: 인기 항목 전달
  Page-->>User: HOT 리스트 렌더링
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

✨Feature

Suggested reviewers

  • Chasyuss

Poem

새싹 훅 두 개 심었어요, 폴짝폴짝 🐇
드롭다운 열면 직무들이 춤을 추네,
토큰은 살짝 확인하고 바람처럼 불러와—
HOT 리스트 반짝, 순위는 숫자처럼 빛나고,
냐옹 아닌 토끼가 코드밭을 뛰어다닌다!


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f2a15e5 and 241c526.

📒 Files selected for processing (4)
  • src/pages/community/Community.tsx (1 hunks)
  • src/pages/community/components/CommunityDropdown.tsx (1 hunks)
  • src/store/useCommunityStore.ts (1 hunks)
  • src/utils/data/community/jobs.ts (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/api-324

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cywin1018 cywin1018 changed the title Feature/api 324 [✨FEATURE] 커뮤니티 api 왼쪽 Sep 4, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (17)
src/utils/data/community/jobs.ts (2)

1-24: 정적 옵션 vs API 데이터 드리프트 방지

드롭다운 옵션이 정적 배열이고 기본값만 API에서 가져오면, API가 제공하는 직무와 목록이 어긋날 수 있습니다. 가능하면 옵션 자체도 API 응답을 우선 사용하고, 이 파일은 오프라인/폴백 용도로만 쓰는 구조를 권장합니다. CommunityDropdown으로 API 리스트를 전달하는 경로를 고려해 주세요.


1-24: 리터럴 타입 고정(as const) 및 타입 내보내기

런타임/타입 안정성을 위해 읽기 전용 배열과 유니온 타입을 노출해두면 이후 스토어/훅 간 타입 일관성이 좋아집니다.

-const jobs: string[] = [
+export const jobs = [
   '요양보호사',
   '간호조무사',
   '보육교사',
   '사회복지사',
   '직업상담사',
   '심리상담사',
   '급식 도우미',
   '사무보조원',
   '회계사무원',
   '수의테크니션',
   '웨딩 헬퍼',
   '미용사 (일반)',
   '미용사 (피부)',
   '미용사 (네일)',
   '미용사 (메이크업)',
   '반려동물미용사',
   '레크리에이션 지도사',
   '바리스타',
   '공인중개사',
   '산후조리사',
-];
-
-export default jobs;
+ ] as const;
+
+export type JobName = typeof jobs[number];
+export default jobs;
src/hook/community/query/useGetCommunityQuery.ts (3)

5-10: queryKey에 불린만 사용하면 토큰 교체 시 재요청이 막힐 수 있음

토큰 갱신(진리값은 그대로 true) 시 캐시 키가 동일해 재조회가 발생하지 않습니다. 토큰(또는 tokenVersion/userId 등 비민감 식별자)을 키에 포함하거나, 로그인/갱신 시점에 invalidate를 트리거하세요.

-export const useGetCommunityQuery = () => {
-  const isLoggedIn =
-    typeof window !== 'undefined' && !!localStorage.getItem('accessToken');
+export const useGetCommunityQuery = () => {
+  const token =
+    typeof window !== 'undefined' ? localStorage.getItem('accessToken') : null;
+  const isLoggedIn = !!token;
 
   return useQuery({
-    queryKey: ['community', isLoggedIn],
+    // 민감정보 노출이 우려되면 token 대신 tokenVersion/userId를 사용하세요.
+    queryKey: ['community', isLoggedIn, token ?? null],

11-19: 토큰 재조회 중복 + 헤더 부착 공통화

토큰을 위에서 구했으니 중복 조회를 제거하세요. 가능하면 Axios 인터셉터에서 Authorization을 공통으로 붙여 개별 훅에서 분기하지 않는 것을 추천합니다.

-    queryFn: async () => {
-      const token =
-        typeof window !== 'undefined'
-          ? localStorage.getItem('accessToken')
-          : null;
-
-      const res = await api.get(
-        '/v1/community/job',
-        token ? { headers: { Authorization: `Bearer ${token}` } } : undefined
-      );
+    queryFn: async () => {
+      const res = await api.get(
+        '/v1/community/job',
+        token ? { headers: { Authorization: `Bearer ${token}` } } : undefined
+      );

21-25: 반환 타입 명시로 사용처 혼동 최소화

res.data 내부에 다시 data가 있는 형태라면 제네릭/타입을 선언해 return을 일관화하세요(예: select로 최종 형태까지 매핑). 현재 CommunityDropdown에서 communityData?.data 접근을 가정하고 있어 계약 고정이 중요합니다.

src/store/useCommunityStore.ts (2)

3-11: JobName 유니온 타입으로 상태를 좁혀 타입 안정성 강화

정적 목록/API 계약이 정해져 있다면 JobName 유니온으로 제한하세요. 초기값은 ''로 두되 setter는 JobName만 받도록 하면 오탈자/미지원 값 유입을 차단할 수 있습니다.

-import { create } from 'zustand';
+import { create } from 'zustand';
+import type { JobName } from '@utils/data/community/jobs';
 
 interface CommunityStore {
-  selectedJobName: string;
-  setSelectedJobName: (jobName: string) => void;
+  selectedJobName: '' | JobName;
+  setSelectedJobName: (jobName: JobName) => void;
+  resetSelectedJob: () => void;
 }
 
 export const useCommunityStore = create<CommunityStore>((set) => ({
   selectedJobName: '',
-  setSelectedJobName: (jobName: string) => set({ selectedJobName: jobName }),
+  setSelectedJobName: (jobName: JobName) => set({ selectedJobName: jobName }),
+  resetSelectedJob: () => set({ selectedJobName: '' }),
 }));

8-11: 선택 유지가 필요하면 persist 미들웨어 고려

새로고침/탭 재방문 시 선택값을 유지하려면 persist를 도입하세요(스토리지 키/버전만 신경 쓰면 됩니다).

src/pages/community/Community.tsx (5)

1-1: 주석 처리된 미사용 import 정리

dead code는 제거하세요.

-//  import DropDownIcon from '@assets/icons/drop_down.svg?react';

17-23: 초기 value/콘솔 로그 제거로 단순화

CommunityDropdown이 스토어를 직접 갱신하므로 부모 value=jobs[0]는 불필요하며 console.log는 제거하세요.

-          <CommunityDropdown
-            options={jobs}
-            value={jobs[0]}
-            onSelect={(value) => {
-              console.log(value);
-            }}
-          />
+          <CommunityDropdown options={jobs} onSelect={() => {}} />

34-37: 빈 선택 시 헤더 가독성 개선

선택 전엔 플레이스홀더를 표시하세요.

-          <div className="text-black font-T04-B">
-            {' '}
-            {selectedJobName} HOT 할 일
-          </div>
+          <div className="text-black font-T04-B">
+            {(selectedJobName || '직무 선택')} HOT 할 일
+          </div>

39-75: 빈 목록/로딩 상태 처리

데이터 없을 때의 UX를 보완하세요(간단 안내문 또는 스켈레톤).

-            {popularTodos.map((item, idx) => (
+            {popularTodos.length === 0 ? (
+              <div className="w-full py-6 text-center text-gray-400 font-C01-R">
+                표시할 항목이 없습니다.
+              </div>
+            ) : (
+            popularTodos.map((item, idx) => (
               <div
                 key={item.id}
                 className="flex w/full flex-row items-start justify-between py-4"
               >
                 <div className="flex flex-row items-center gap-[15px]">
                   <div className="text-purple-500 font-T05-SB">{idx + 1}</div>
                   <div className="flex flex-row items-center gap-[15px]">
                     <img
-                      src={item.imageUrl}
+                      src={item.imageUrl}
+                      loading="lazy"
                       alt="프로필이미지"
                       className="h-[30px] w-[30px] rounded-full bg-gray-50"
                     />
 
                     <div className="flex flex-col">
                       <div className="flex w-full flex-row items-start justify-between gap-[10px]">
                         <div className="flex-1 break-words text-black font-B01-SB">
                           {item.description}
                         </div>
                         <div className="mr-2 shrink-0 whitespace-nowrap text-gray-500 font-C01-R">
                           {item.dDay}
                         </div>
                       </div>
                       <div className="mt-1 text-gray-500 font-C01-R">
                         {item.name}
                       </div>
                     </div>
                   </div>
                 </div>
 
                 <div className="flex flex-row items-center gap-[6px] text-purple-500">
                   <Bookmark />
                   <span className="font-B03-SB">{item.saveCount}</span>
                 </div>
               </div>
-            ))}
+            ))}
+            )}

7-12: 정적 옵션과 API 기본값 불일치 가능성 점검

API가 반환한 기본 직무가 jobs 배열에 없으면 선택 라벨과 옵션 목록이 어긋납니다. 옵션도 API 리스트를 전달하는 구조로 이관하는 것을 권장합니다. 또한 useGetHotPopularQuery 내부 console.log도 제거해 주세요.

src/hook/community/query/useGetHotPopularQuery.ts (2)

29-35: 불필요한 콘솔 출력 제거 및 응답 타입 안전화(필요 시 토큰 헤더 추가)

운영에서 console.log는 지양하고, Axios 제네릭으로 응답을 안전하게 타이핑하세요. 엔드포인트가 인증 필요할 수 있으니 토큰이 있으면 헤더에 동봉하도록 제안합니다.

다음처럼 정리하면 됩니다:

     queryFn: async () => {
-      const res = await api.get('/v1/community/todos/popular', {
-        params: { jobName: selectedJobName },
-      });
-      console.log(res.data);
-      const body = res.data as HotPopularApiResponse;
-      return Array.isArray(body?.data) ? body.data : [];
+      const token =
+        typeof window !== 'undefined'
+          ? localStorage.getItem('accessToken')
+          : null;
+
+      const res = await api.get<HotPopularApiResponse>(
+        '/v1/community/todos/popular',
+        {
+          params: { jobName: selectedJobName },
+          ...(token ? { headers: { Authorization: `Bearer ${token}` } } : {}),
+        }
+      );
+      if (process.env.NODE_ENV === 'development') {
+        // eslint-disable-next-line no-console
+        console.debug('[useGetHotPopularQuery]', res.data);
+      }
+      return Array.isArray(res.data?.data) ? res.data.data : [];
     },

36-38: 초기/플레이스홀더 데이터 지정으로 널 가드 단순화

소비 측에서 data ?? [] 패턴을 줄이려면 placeholderData로 빈 배열을 넣어 두세요.

     staleTime: 1000 * 60 * 5,
     refetchOnWindowFocus: false,
+    placeholderData: [] as HotPopularItem[],
src/pages/community/components/CommunityDropdown.tsx (3)

24-24: 초기 렌더에서 플레이스홀더를 보이게 하려면 기본값을 ''로 시작

현재는 API 응답 전에도 options[0]이 라벨로 노출됩니다. UX 관점에서 ‘선택’ 플레이스홀더를 유지하려면 기본값을 ''로 두는 편이 자연스럽습니다.

-  const [selected, setSelected] = useState<T | ''>(value || (options[0] ?? ''));
+  const [selected, setSelected] = useState<T | ''>(value || '');

67-75: 접근성: 토글 영역에 버튼 롤/키보드 핸들링 추가

키보드 접근성을 위해 role/tabIndex/Enter·Space 처리 추가를 권장합니다.

-      <div className="flex flex-row items-center gap-[18px]" onClick={toggle}>
+      <div
+        className="flex flex-row items-center gap-[18px]"
+        role="button"
+        tabIndex={0}
+        onClick={toggle}
+        onKeyDown={(e) => {
+          if (e.key === 'Enter' || e.key === ' ') toggle();
+        }}
+      >

43-51: API 응답 가공 로직의 타입 안정성 보완

unknown 기반 캐스팅 대신 지역 타입을 정의해 좁히면 안전합니다. 예: type CommunityData = { data?: string | { jobName?: string }[] }.

-    const raw = (communityData as { data?: unknown } | undefined)?.data;
+    type CommunityData = { data?: string | { jobName?: string }[] };
+    const raw = (communityData as CommunityData | undefined)?.data;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5fabd17 and f2a15e5.

📒 Files selected for processing (6)
  • src/hook/community/query/useGetCommunityQuery.ts (1 hunks)
  • src/hook/community/query/useGetHotPopularQuery.ts (1 hunks)
  • src/pages/community/Community.tsx (2 hunks)
  • src/pages/community/components/CommunityDropdown.tsx (1 hunks)
  • src/store/useCommunityStore.ts (1 hunks)
  • src/utils/data/community/jobs.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/hook/community/query/useGetHotPopularQuery.ts (1)
src/store/useCommunityStore.ts (1)
  • useCommunityStore (8-11)
src/pages/community/components/CommunityDropdown.tsx (3)
src/hook/useDropdown.ts (1)
  • useDropdown (3-33)
src/hook/community/query/useGetCommunityQuery.ts (1)
  • useGetCommunityQuery (4-26)
src/store/useCommunityStore.ts (1)
  • useCommunityStore (8-11)
src/pages/community/Community.tsx (3)
src/store/useCommunityStore.ts (1)
  • useCommunityStore (8-11)
src/hook/community/query/useGetHotPopularQuery.ts (1)
  • useGetHotPopularQuery (22-39)
src/pages/community/components/CommunityDropdown.tsx (1)
  • CommunityDropdown (16-106)
🔇 Additional comments (2)
src/hook/community/query/useGetHotPopularQuery.ts (1)

25-28: queryKey/enable 조건 구성 적절

직무 선택값에 종속된 queryKey와 enabled 가드가 정확합니다. 불필요한 호출을 잘 막습니다.

src/pages/community/components/CommunityDropdown.tsx (1)

30-41: 부모가 첫 번째 옵션값을 명시적으로 지정하는 경우 무시될 수 있음

value && value !== (options[0] as T) 조건 때문에, 부모가 런타임에 의도적으로 options[0]을 설정해도 반영되지 않을 수 있습니다. “초기 마운트 한정 무시”가 목적이라면 마운트 여부 플래그로 1회만 스킵하도록 조정하는지 확인 부탁드립니다.

원하시면 useRef로 초깃값만 스킵하는 패턴으로 리팩터 제안드릴게요.

Comment on lines +30 to +41
useEffect(() => {
if (!initializedFromApi) return; // API 초기 반영 전에는 옵션/외부값으로 덮어쓰지 않음
// 부모가 초기 표시용으로 전달한 첫 옵션 값은 무시하고, 실제 변경만 반영
if (value && value !== (options[0] as T)) {
setSelected(value);
return;
}
if (!userSelected) {
setSelected((prev) => prev || (options[0] ?? ''));
}
}, [value, options, userSelected, initializedFromApi]);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

전역 스토어 동기화 누락: 외부 value 변화 시 selectedJobName이 갱신되지 않음

value가 부모에서 변경될 때 로컬 selected만 바뀌고 setSelectedJobName이 호출되지 않아, 전역 상태를 사용하는 다른 훅(useGetHotPopularQuery)과 UI가 불일치할 수 있습니다.

간단히 selected 변경을 전역 스토어와 항상 동기화하는 이펙트를 추가하는 방식을 권장합니다(중복 호출 안전).

   const { setSelectedJobName } = useCommunityStore();
 
+  // 로컬 선택값이 바뀌면 항상 전역 스토어와 동기화
+  useEffect(() => {
+    if (selected !== '') {
+      setSelectedJobName(String(selected));
+    }
+  }, [selected, setSelectedJobName]);

추가로, 위 이펙트를 도입하면 아래 두 곳의 직접 호출은 제거해도 됩니다(중복 디스패치 감소).

  • Line 56: setSelectedJobName(String(apiDefault));
  • Line 91: setSelectedJobName(String(opt));
    원하시면 제거용 diff도 드리겠습니다.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (!initializedFromApi) return; // API 초기 반영 전에는 옵션/외부값으로 덮어쓰지 않음
// 부모가 초기 표시용으로 전달한 첫 옵션 값은 무시하고, 실제 변경만 반영
if (value && value !== (options[0] as T)) {
setSelected(value);
return;
}
if (!userSelected) {
setSelected((prev) => prev || (options[0] ?? ''));
}
}, [value, options, userSelected, initializedFromApi]);
const { setSelectedJobName } = useCommunityStore();
// 로컬 선택값이 바뀌면 항상 전역 스토어와 동기화
useEffect(() => {
if (selected !== '') {
setSelectedJobName(String(selected));
}
}, [selected, setSelectedJobName]);
useEffect(() => {
if (!initializedFromApi) return; // API 초기 반영 전에는 옵션/외부값으로 덮어쓰지 않음
// 부모가 초기 표시용으로 전달한 첫 옵션 값은 무시하고, 실제 변경만 반영
if (value && value !== (options[0] as T)) {
setSelected(value);
return;
}
if (!userSelected) {
setSelected((prev) => prev || (options[0] ?? ''));
}
}, [value, options, userSelected, initializedFromApi]);
🤖 Prompt for AI Agents
In src/pages/community/components/CommunityDropdown.tsx around lines 30 to 41,
the effect updates local selected when props change but never syncs local
selected to the global store, causing selectedJobName to lag; add a new
useEffect that runs when selected changes and always calls
setSelectedJobName(String(selected)) (ensure it is safe for duplicate calls),
and after adding this syncing effect remove the redundant direct dispatches at
lines 56 (`setSelectedJobName(String(apiDefault));`) and 91
(`setSelectedJobName(String(opt));`) to avoid duplicate updates.

Copy link
Member

@Chasyuss Chasyuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했어용

@cywin1018 cywin1018 merged commit 03eadb5 into develop Sep 4, 2025
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants