-
Notifications
You must be signed in to change notification settings - Fork 1
Develop #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop #13
Changes from all commits
6591a88
d22b962
502d804
7174562
8444691
8260de7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| "use client"; | ||
|
|
||
| import { useEffect, useRef, useState } from "react"; | ||
|
|
||
| interface UseCarouselOptions<T> { | ||
| items: T[]; | ||
| onSelect?: (item: T) => void; | ||
| } | ||
|
|
||
| export function useCarousel<T extends { id: string }>({ | ||
| items, | ||
| onSelect, | ||
| }: UseCarouselOptions<T>) { | ||
| const [currentIndex, setCurrentIndex] = useState(0); | ||
| const onSelectRef = useRef(onSelect); | ||
| const isInitialMount = useRef(true); | ||
|
|
||
| // onSelect์ ์ต์ ๊ฐ์ ref์ ์ ์ฅ | ||
| useEffect(() => { | ||
| onSelectRef.current = onSelect; | ||
| }, [onSelect]); | ||
|
|
||
| const currentItem = items?.[currentIndex]; | ||
|
|
||
| // currentIndex๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์์๋ก ์ ๋ฌ (์ด๊ธฐ ๋ง์ดํธ ์ ์ธ) | ||
| useEffect(() => { | ||
| // ์ด๊ธฐ ๋ง์ดํธ ์์๋ ์คํํ์ง ์์ | ||
| if (isInitialMount.current) { | ||
| isInitialMount.current = false; | ||
| return; | ||
| } | ||
|
|
||
| if (currentItem && onSelectRef.current) { | ||
| onSelectRef.current(currentItem); | ||
| } | ||
| }, [currentItem]); | ||
|
|
||
| const handlePrevious = () => { | ||
| setCurrentIndex((prev) => { | ||
| const newIndex = prev === 0 ? items.length - 1 : prev - 1; | ||
| const newItem = items[newIndex]; | ||
| if (newItem) { | ||
| onSelect?.(newItem); | ||
| } | ||
| return newIndex; | ||
| }); | ||
| }; | ||
|
|
||
| const handleNext = () => { | ||
| setCurrentIndex((prev) => { | ||
| const newIndex = prev === items.length - 1 ? 0 : prev + 1; | ||
| const newItem = items[newIndex]; | ||
| if (newItem) { | ||
| onSelect?.(newItem); | ||
| } | ||
| return newIndex; | ||
| }); | ||
| }; | ||
|
|
||
| const handleDotClick = (index: number) => { | ||
| setCurrentIndex(index); | ||
| const item = items[index]; | ||
| if (item) { | ||
| onSelect?.(item); | ||
| } | ||
| }; | ||
|
Comment on lines
+26
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The handlers ( Since ๐ Remove redundant useEffect or direct callsOption 1: Remove the useEffect (recommended - handlers already call onSelect) - // currentIndex๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์์๋ก ์ ๋ฌ (์ด๊ธฐ ๋ง์ดํธ ์ ์ธ)
- useEffect(() => {
- // ์ด๊ธฐ ๋ง์ดํธ ์์๋ ์คํํ์ง ์์
- if (isInitialMount.current) {
- isInitialMount.current = false;
- return;
- }
-
- if (currentItem && onSelectRef.current) {
- onSelectRef.current(currentItem);
- }
- }, [currentItem]);Option 2: Keep useEffect and remove direct calls in handlers const handlePrevious = () => {
setCurrentIndex((prev) => {
const newIndex = prev === 0 ? items.length - 1 : prev - 1;
- const newItem = items[newIndex];
- if (newItem) {
- onSelect?.(newItem);
- }
return newIndex;
});
};๐ค Prompt for AI Agents |
||
|
|
||
| return { | ||
| currentIndex, | ||
| currentItem, | ||
| handlePrevious, | ||
| handleNext, | ||
| handleDotClick, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| "use client"; | ||
|
|
||
| import { useRouter } from "next/navigation"; | ||
| import { | ||
| detailSituations, | ||
| type SituationId, | ||
| } from "../practice/_constants/detailSituations"; | ||
|
|
||
| export function useRandomPractice() { | ||
| const router = useRouter(); | ||
|
|
||
| const getRandomSituation = () => { | ||
| // ๋ชจ๋ ์์ธ์ํฉ์ ํํํํ์ฌ ๋ฐฐ์ด๋ก ๋ง๋ค๊ธฐ | ||
| const allDetailSituations: Array<{ | ||
| situationId: SituationId; | ||
| detailId: string; | ||
| }> = []; | ||
|
|
||
| (Object.keys(detailSituations) as SituationId[]).forEach((situationId) => { | ||
| detailSituations[situationId].forEach((detail) => { | ||
| allDetailSituations.push({ | ||
| situationId, | ||
| detailId: detail.id, | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| // ๋๋ค์ผ๋ก ํ๋ ์ ํ | ||
| const randomIndex = Math.floor(Math.random() * allDetailSituations.length); | ||
| return allDetailSituations[randomIndex]; | ||
| }; | ||
|
|
||
| const navigateToRandomPractice = () => { | ||
| const selected = getRandomSituation(); | ||
| router.push(`/practice/${selected.situationId}/${selected.detailId}/dial`); | ||
|
Comment on lines
+28
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a guard for empty array access. If ๐ก๏ธ Suggested defensive check const navigateToRandomPractice = () => {
const selected = getRandomSituation();
+ if (!selected) return;
router.push(`/practice/${selected.situationId}/${selected.detailId}/dial`);
};๐ค Prompt for AI Agents |
||
| }; | ||
|
|
||
| return { | ||
| navigateToRandomPractice, | ||
| }; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Index may become stale when
itemsarray changes.If the
itemsarray shrinks (e.g., from 4 items to 2),currentIndexcould remain at an invalid position, causingcurrentItemto beundefinedand potential runtime errors in consumers.๐ก๏ธ Suggested fix to reset index when items change
๐ค Prompt for AI Agents