Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ import type { KeyboardEvent, MouseEvent, PointerEvent } from "react";
import { convertDurationToTimeText } from "@/utils/todo/todo-time";

const isInteractiveElement = (target: EventTarget | null) =>
target instanceof HTMLElement &&
Boolean(target.closest("button, input, label"));
target instanceof Element && Boolean(target.closest("button, input, label"));

export interface HomeTodoCardProps {
todoId: number;
Expand Down
14 changes: 14 additions & 0 deletions apps/timo-web/hooks/todo-modal/detail/use-detail-subtask-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ export const useDetailSubtaskField = ({
const inputRefs = useRef<Array<HTMLTextAreaElement | null>>([]);
const pendingFocusIndex = useRef<number | null>(null);

useEffect(() => {
setSubtaskInputs((prev) =>
prev.map((input) => {
const serverSubtask = subtasks.find(
(subtask) => subtask.subtaskId === input.subtaskId,
);
if (!serverSubtask || serverSubtask.completed === input.completed) {
return input;
}
return { ...input, completed: serverSubtask.completed };
}),
);
}, [subtasks]);

Comment on lines +43 to +56

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

불필요한 재렌더링을 방지하도록 상태 업데이트 로직 개선

서브태스크 동기화 로직, 필요한 부분만 잘 캐치해서 작성해주셨네요! 센스 최고예요! 👏

현재 prev.map을 사용하면 실제 completed 값이 변경되지 않았더라도 항상 새로운 배열이 생성되어 반환됩니다. 이로 인해 subtasks 배열의 참조가 바뀔 때마다 상태가 업데이트되어 불필요한 재렌더링이 발생할 수 있습니다.

상태를 업데이트할 때 실제 변경 사항이 있는지를 추적하여, 변경이 없을 경우에는 이전 상태(prev)의 참조를 그대로 반환하도록 개선하면 React가 렌더링을 건너뛰게 할 수 있습니다.

관련해서는 React 공식 문서: State 업데이트 건너뛰기를 참고해 보시면 더 깊이 이해하는 데 도움이 될 거예요!

💡 재렌더링 방지를 위한 개선 제안
   useEffect(() => {
-    setSubtaskInputs((prev) =>
-      prev.map((input) => {
+    setSubtaskInputs((prev) => {
+      let hasChanges = false;
+      const next = prev.map((input) => {
         const serverSubtask = subtasks.find(
           (subtask) => subtask.subtaskId === input.subtaskId,
         );
         if (!serverSubtask || serverSubtask.completed === input.completed) {
           return input;
         }
+        hasChanges = true;
         return { ...input, completed: serverSubtask.completed };
-      }),
-    );
+      });
+      return hasChanges ? next : prev;
+    });
   }, [subtasks]);
📝 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(() => {
setSubtaskInputs((prev) =>
prev.map((input) => {
const serverSubtask = subtasks.find(
(subtask) => subtask.subtaskId === input.subtaskId,
);
if (!serverSubtask || serverSubtask.completed === input.completed) {
return input;
}
return { ...input, completed: serverSubtask.completed };
}),
);
}, [subtasks]);
useEffect(() => {
setSubtaskInputs((prev) => {
let hasChanges = false;
const next = prev.map((input) => {
const serverSubtask = subtasks.find(
(subtask) => subtask.subtaskId === input.subtaskId,
);
if (!serverSubtask || serverSubtask.completed === input.completed) {
return input;
}
hasChanges = true;
return { ...input, completed: serverSubtask.completed };
});
return hasChanges ? next : prev;
});
}, [subtasks]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/timo-web/hooks/todo-modal/detail/use-detail-subtask-field.ts` around
lines 43 - 56, Update the state updater in the useEffect synchronization for
subtasks to track whether any completed value changes; return the original prev
reference when no matching subtask requires an update, and only return a new
mapped array when at least one value changes.

useEffect(() => {
if (pendingFocusIndex.current === null) return;

Expand Down
Loading