From d52c7df408ca603c20e9b5b5c9fb0244648a95eb Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 10 Jun 2026 14:04:43 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20Fix=20missing=20dependencies=20a?= =?UTF-8?q?nd=20setState=20in=20useEffect=20anti-pattern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- commit-msg.txt | 6 ++++ .../components/org/create-project-modal.tsx | 29 +++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 commit-msg.txt diff --git a/commit-msg.txt b/commit-msg.txt new file mode 100644 index 0000000..3101493 --- /dev/null +++ b/commit-msg.txt @@ -0,0 +1,6 @@ +๐Ÿงน Fix missing dependencies and setState in useEffect anti-pattern + +๐ŸŽฏ What: Refactored CreateProjectModal to replace an anti-pattern `useEffect` with explicit state reset in the `handleOpenChange` event handler. +๐Ÿ’ก Why: Resolves a "Missing Dependencies in useEffect" code health issue. By handling side effects directly in response to user actions rather than watching state variables, we avoid redundant runs, prevent infinite loops, and eliminate the cascading renders caused by calling setState synchronously inside an effect. +โœ… Verification: Ran `pnpm eslint` locally for the component to ensure all React hooks warnings are resolved. Verified tests and Next.js production build pass cleanly. Code behavior remains unchanged while cleanly passing static analysis. +โœจ Result: The code is simpler, aligns with React best practices ("You Might Not Need an Effect"), and fixes static analysis warnings while preventing potential stale closure bugs. diff --git a/packages/web/src/components/org/create-project-modal.tsx b/packages/web/src/components/org/create-project-modal.tsx index 5cee569..db0ebe5 100644 --- a/packages/web/src/components/org/create-project-modal.tsx +++ b/packages/web/src/components/org/create-project-modal.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState, useEffect } from 'react' +import { useState, useCallback } from 'react' import { AlertDialog, AlertDialogContent, @@ -28,18 +28,17 @@ export function CreateProjectModal({ const [name, setName] = useState('') const mutation = useCreateProject(orgSlug) - useEffect(() => { - if (!open) { - setName('') - mutation.reset() - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [open]) - - const handleOpenChange = (next: boolean) => { - if (!next && mutation.isPending) return - onOpenChange(next) - } + const handleOpenChange = useCallback( + (next: boolean) => { + if (!next && mutation.isPending) return + if (!next) { + setName('') + mutation.reset() + } + onOpenChange(next) + }, + [mutation, onOpenChange] + ) const handleSubmit = (e: React.FormEvent) => { e.preventDefault() @@ -49,7 +48,7 @@ export function CreateProjectModal({ { name: trimmed }, { onSuccess: () => { - onOpenChange(false) + handleOpenChange(false) }, } ) @@ -95,7 +94,7 @@ export function CreateProjectModal({ variant="outline" size="sm" disabled={mutation.isPending} - onClick={() => onOpenChange(false)} + onClick={() => handleOpenChange(false)} > ์ทจ์†Œ