Skip to content

#5 [Feat] Headless 공통 컴포넌트 및 Hooks 초기 구조 구현#6

Merged
jung518 merged 3 commits intodevfrom
feat/#5
Apr 9, 2026
Merged

#5 [Feat] Headless 공통 컴포넌트 및 Hooks 초기 구조 구현#6
jung518 merged 3 commits intodevfrom
feat/#5

Conversation

@jung518
Copy link
Copy Markdown
Contributor

@jung518 jung518 commented Apr 9, 2026

연관된 이슈

체크리스트

  • Reviewer에 팀원들을 선택했나요?
  • Assignees에 본인을 선택했나요?
  • 컨벤션에 맞는 Labels를 선택했나요?
  • Development에 이슈를 연동했나요?
  • Project를 연동했나요?
  • Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  • 컨벤션을 지키고 있나요?
  • 로컬에서 실행했을 때 에러가 발생하지 않나요?
  • 팀원들에게 PR 링크 공유를 했나요?

기획 및 구현한 내용

Headless Hooks와 공통 UI 컴포넌트를 통합하여 재사용 가능한 상태 관리 및 UI 구조를 구현했습니다.

주요 구현 사항

1. Hooks (로직)

  • useToggle: boolean 상태 관리 및 toggle 함수 구현
  • useModal: open/close 상태 관리, 하드웨어 뒤로가기 및 outside click 감지
  • useDropdown: open/close 상태, 선택 값 관리
  • useInfiniteScroll: 스크롤 위치 감지, threshold 설정, fetch trigger 함수 연결
  • useForm: values/errors 상태 관리, handleChange, handleSubmit 구현, validation 연동

2. Headless Components

  • Button: onPress, disabled, loading 처리
  • Input: value, onChange, error, placeholder 지원
  • FormProvider: FormContext 생성 및 상태 공유
  • Modal: isOpen, onClose, children 렌더링 및 outside click 처리
  • Dropdown: options, selected, onSelect 이벤트 처리

3. Validation Logic

  • required 검사
  • email 검사
  • 에러 메시지 반환 구조 설계

4. Loading / Skeleton

  • Loading: boolean 기반 표시 처리
  • Skeleton: 재사용 가능한 기본 박스 UI 구조 구현

Summary by CodeRabbit

  • New Features

    • Added UI components: Button, Dropdown, Input, Loading indicator, Modal, and Skeleton loader
    • Introduced form management (provider + hook) and form-related hooks for state, validation, and submission
    • Added utility hooks: dropdown control, infinite scroll handling, modal control, and toggle helper
    • Added validation utilities for required fields and email format
  • Chores

    • Removed placeholder/comments from common component files

@jung518 jung518 requested a review from daeun0726 April 9, 2026 09:56
@jung518 jung518 self-assigned this Apr 9, 2026
@jung518 jung518 added the Feature 새로운 기능 구현 label Apr 9, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Added a set of new React Native UI components (Button, Input, Dropdown, Loading, Modal, Skeleton), form context and hooks for state management (useForm, useToggle, useDropdown, useModal, useInfiniteScroll), and validation utilities; removed placeholder comments from two common files.

Changes

Cohort / File(s) Summary
UI Components
src/components/Button/Button.tsx, src/components/Input/Input.tsx, src/components/Dropdown/Dropdown.tsx, src/components/Loading/Loading.tsx, src/components/Modal/Modal.tsx, src/components/Skeleton/Skeleton.tsx
Added six new React Native components. Notable behaviors: Button supports loading/disabled and renders ActivityIndicator; Input integrates with FormContext; Dropdown renders selectable options; Loading exposes typed props; Modal supports backdrop dismiss; Skeleton accepts width/height props.
Form Context & Hooks (form)
src/contexts/FormContext.tsx, src/hooks/useForm.ts
Added FormProvider and useForm: context provider, hook to manage values/errors, handleChange, validation, and conditional submit.
Utility Hooks
src/hooks/useToggle.ts, src/hooks/useDropdown.ts, src/hooks/useModal.ts, src/hooks/useInfiniteScroll.ts
Added generic state hooks: useToggle (boolean control), useDropdown (open/select), useModal (open/close with BackHandler integration), useInfiniteScroll (guarded async fetch with isFetching).
Validation Utilities
src/utils/validation.ts
Added required and email validators returning Korean error messages.
Cleanup (comments)
src/components/common/Button.tsx, src/components/common/Input.tsx
Removed placeholder comments from two common files (no functional code changes).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

🐰
New buttons, modals, forms in view,
I hopped and stitched a hook or two;
Inputs listen, dropdowns sing,
Loading lights and skeletons bring —
Hop on, build something new! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly matches the changeset: it describes implementing initial headless components and hooks structure, which is exactly what the PR delivers across multiple new component and hook files.
Description check ✅ Passed The PR description covers all required template sections with substantial detail: related issue (#5), completed checklist items, planning/implementation overview, main implementation items, and organized feature breakdown across Hooks, Headless Components, Validation, and Loading/Skeleton.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#5

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 5

🧹 Nitpick comments (6)
src/components/Dropdown/Dropdown.tsx (1)

23-24: Use a stable key for dropdown options.

Line 24 uses idx as the key, which can cause item identity issues when options are reordered or filtered. Prefer a stable, item-derived key.

🔧 Proposed change
-export const Dropdown = ({ options, onSelect }: any) => {
+export const Dropdown = ({ options, onSelect }: any) => {
   return (
     <View>
       {options.map((item: any, idx: number) => (
-        <Pressable key={idx} onPress={() => onSelect(item)}>
+        <Pressable key={String(item)} onPress={() => onSelect(item)}>
           <Text>{item}</Text>
         </Pressable>
       ))}
     </View>
   );
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Dropdown/Dropdown.tsx` around lines 23 - 24, The dropdown
options map uses the array index (idx) as the React key in the Pressable created
inside options.map, which can break identity when items reorder or filter;
change the key to a stable, item-derived identifier (e.g., item.id or another
unique property) by updating the key on the Pressable in the options.map
callback and ensure the data passed to onSelect remains unchanged (use item.id
if available, otherwise derive a stable unique value from the item).
src/hooks/useForm.ts (1)

18-20: Consider memoizing handlers to prevent unnecessary re-renders.

handleChange and handleSubmit are recreated on every render. If these are passed to child components (via FormProvider), it may trigger unnecessary re-renders. Using useCallback would stabilize the references.

♻️ Suggested memoization
+import { useState, useCallback } from 'react';
-import { useState } from 'react';

...

-  const handleChange = (name: string, value: any) => {
-    setValues((prev: any) => ({ ...prev, [name]: value }));
-  };
+  const handleChange = useCallback((name: string, value: any) => {
+    setValues((prev: any) => ({ ...prev, [name]: value }));
+  }, []);

-  const handleSubmit = () => {
+  const handleSubmit = useCallback(() => {
     const newErrors = validate ? validate(values) : {};
     setErrors(newErrors);

     if (Object.keys(newErrors).length === 0) {
-      onSubmit(values);
+      onSubmit?.(values);
     }
-  };
+  }, [values, validate, onSubmit]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useForm.ts` around lines 18 - 20, handleChange and handleSubmit are
recreated each render causing potential child re-renders; wrap them in
React.useCallback to stabilize references. Update handleChange to
useCallback((name, value) => setValues(prev => ({ ...prev, [name]: value })),
[setValues]) and memoize handleSubmit similarly with useCallback, including its
dependencies (e.g., values, onSubmit or any validation functions) so the
returned handlers from the hook remain stable when passed through FormProvider.
src/hooks/useModal.ts (1)

5-15: Documentation does not match implementation.

The JSDoc mentions "ESC로 닫기" (ESC to close) and "outside click 감지" (outside click detection), but:

  • ESC key handling is not applicable in React Native
  • Outside click detection is handled in the Modal.tsx component, not in this hook

Consider updating the documentation to accurately describe the hook's functionality: hardware back button handling on Android.

📝 Suggested documentation fix
 /**
  * Modal 상태 관리 Hook
  *
  * 기능:
  * - open / close 상태 관리
- * - ESC로 닫기
- * - outside click 감지
+ * - Android 하드웨어 백버튼으로 닫기
  *
  * `@example`
  * const { isOpen, open, close } = useModal();
  */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useModal.ts` around lines 5 - 15, Update the JSDoc for the useModal
hook to accurately reflect its behavior: remove references to "ESC로 닫기" and
"outside click 감지", and instead document that it manages open/close state and
handles Android hardware back button behavior (with outside click handled in
Modal.tsx); reference the hook name useModal and the Modal.tsx component so
maintainers know where outside-click logic lives.
src/contexts/FormContext.tsx (1)

15-19: Consider adding type definitions for type safety.

Both FormContext and FormProvider use any, losing type safety. Consider defining an interface for the form context value.

📝 Suggested type definitions
+interface FormContextValue {
+  values: Record<string, any>;
+  errors: Record<string, string>;
+  handleChange: (name: string, value: any) => void;
+  handleSubmit: () => void;
+}
+
+interface FormProviderProps {
+  children: React.ReactNode;
+  value: FormContextValue;
+}
+
-const FormContext = createContext<any>(null);
+const FormContext = createContext<FormContextValue | null>(null);

-export const FormProvider = ({ children, value }: any) => {
+export const FormProvider = ({ children, value }: FormProviderProps) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/contexts/FormContext.tsx` around lines 15 - 19, FormContext and
FormProvider use any which removes type safety; define a specific interface
(e.g., FormContextValue) describing the shape of the context (fields, methods
like submit/reset, loading flags, etc.), change createContext to
createContext<FormContextValue | null>(null), and update FormProvider props to
accept children: React.ReactNode and value: FormContextValue (or
Partial/FormContextValue | null if appropriate). Also export the interface/type
so consumers can import it and avoid using any in useContext(FormContext) calls.
src/components/Modal/Modal.tsx (2)

21-21: Replace any with explicit prop types.

Using any loses type safety and IDE support. Define proper prop types for better maintainability and developer experience.

📝 Suggested type definition
+interface ModalProps {
+  isOpen: boolean;
+  onClose: () => void;
+  children: React.ReactNode;
+}
+
-export const Modal = ({ isOpen, onClose, children }: any) => {
+export const Modal = ({ isOpen, onClose, children }: ModalProps) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Modal/Modal.tsx` at line 21, The Modal component currently
types its props as any; replace this with a concrete prop type (e.g., define an
interface or type named ModalProps) and annotate the Modal signature accordingly
to restore type safety: include isOpen: boolean, onClose: () => void, and
children: React.ReactNode (or ReactElement) as required/optional per usage, and
export/apply the ModalProps type (or use React.FC<ModalProps>) so IDEs and the
compiler enforce correct prop usage for Modal, isOpen, onClose and children.

24-30: Backdrop lacks visual styling — users won't see a dimmed overlay.

The outer View with flex: 1 has no background color, so the backdrop will be invisible. Typically, modals use a semi-transparent dark background to indicate the overlay area and improve UX.

🎨 Suggested backdrop styling
       <TouchableWithoutFeedback onPress={onClose}>
-        <View style={{ flex: 1 }}>
+        <View style={{ flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'center', alignItems: 'center' }}>
           <TouchableWithoutFeedback>
             <View>{children}</View>
           </TouchableWithoutFeedback>
         </View>
       </TouchableWithoutFeedback>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Modal/Modal.tsx` around lines 24 - 30, The outer backdrop View
inside the Modal component (wrapped by TouchableWithoutFeedback with onClose)
has only { flex: 1 } so it's invisible; update the outer View's style (the View
wrapping the inner TouchableWithoutFeedback/children) to include a
semi-transparent dark background (e.g., backgroundColor: 'rgba(0,0,0,0.5)') and
proper positioning (center the inner content) so the overlay is visible; keep
the inner TouchableWithoutFeedback/children layout intact so clicks on the
backdrop still call onClose while taps inside the inner View do not.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Button/Button.tsx`:
- Line 24: The Button component currently forces non-text children into a <Text>
(see the JSX using loading ? <ActivityIndicator /> : <Text>{children}</Text>),
which breaks when children are icons or other React elements; update the render
so that when loading you show <ActivityIndicator />, otherwise render children
as-is, but still wrap only primitive text/number children in <Text> (use a
runtime check like typeof children === 'string' || typeof children === 'number'
or React.Children.toArray(children).every(c => typeof c === 'string' || typeof c
=== 'number') to decide whether to wrap), and ensure the Button's prop type for
children is React.ReactNode (or preserves the existing contract) so icons and
layout nodes are supported.

In `@src/contexts/FormContext.tsx`:
- Around line 21-23: useFormContext currently returns the raw FormContext which
can be null if called outside a FormProvider; update useFormContext to check for
a null context and throw a clear error (e.g., "useFormContext must be used
within a FormProvider") so consumers like Input.tsx won't crash with cryptic
runtime errors when accessing values[name]; modify the function that returns
useContext(FormContext) to perform this defensive null guard and throw a
descriptive exception if context is missing.

In `@src/hooks/useForm.ts`:
- Around line 22-29: The handleSubmit function calls onSubmit(values) unguarded
which throws if onSubmit is missing; update handleSubmit (in useForm.ts) to
check that onSubmit is a function before invoking (e.g., if
(Object.keys(newErrors).length === 0 && typeof onSubmit === "function")
onSubmit(values)) and otherwise no-op or log a warning so setErrors/validate
behavior stays the same and no runtime TypeError occurs.

In `@src/hooks/useInfiniteScroll.ts`:
- Around line 19-21: In useInfiniteScroll, ensure isFetching is always reset by
wrapping the fetchMore() call in a try/finally: call setIsFetching(true) before
invoking fetchMore(), await fetchMore() inside a try block, and call
setIsFetching(false) in the finally block so that setIsFetching(false) runs even
if fetchMore() rejects; update the logic around setIsFetching and fetchMore in
the hook to use this try/finally pattern.

In `@src/utils/validation.ts`:
- Around line 11-13: The required validator (function required) currently treats
whitespace-only strings as valid; update required to trim the input before
checking so that values like "   " are considered empty—i.e., call value =
value?.trim() (or equivalent) then if (!value) return '필수 입력' else return ''.
Ensure you only modify the required function and preserve its return messages
and type signature.

---

Nitpick comments:
In `@src/components/Dropdown/Dropdown.tsx`:
- Around line 23-24: The dropdown options map uses the array index (idx) as the
React key in the Pressable created inside options.map, which can break identity
when items reorder or filter; change the key to a stable, item-derived
identifier (e.g., item.id or another unique property) by updating the key on the
Pressable in the options.map callback and ensure the data passed to onSelect
remains unchanged (use item.id if available, otherwise derive a stable unique
value from the item).

In `@src/components/Modal/Modal.tsx`:
- Line 21: The Modal component currently types its props as any; replace this
with a concrete prop type (e.g., define an interface or type named ModalProps)
and annotate the Modal signature accordingly to restore type safety: include
isOpen: boolean, onClose: () => void, and children: React.ReactNode (or
ReactElement) as required/optional per usage, and export/apply the ModalProps
type (or use React.FC<ModalProps>) so IDEs and the compiler enforce correct prop
usage for Modal, isOpen, onClose and children.
- Around line 24-30: The outer backdrop View inside the Modal component (wrapped
by TouchableWithoutFeedback with onClose) has only { flex: 1 } so it's
invisible; update the outer View's style (the View wrapping the inner
TouchableWithoutFeedback/children) to include a semi-transparent dark background
(e.g., backgroundColor: 'rgba(0,0,0,0.5)') and proper positioning (center the
inner content) so the overlay is visible; keep the inner
TouchableWithoutFeedback/children layout intact so clicks on the backdrop still
call onClose while taps inside the inner View do not.

In `@src/contexts/FormContext.tsx`:
- Around line 15-19: FormContext and FormProvider use any which removes type
safety; define a specific interface (e.g., FormContextValue) describing the
shape of the context (fields, methods like submit/reset, loading flags, etc.),
change createContext to createContext<FormContextValue | null>(null), and update
FormProvider props to accept children: React.ReactNode and value:
FormContextValue (or Partial/FormContextValue | null if appropriate). Also
export the interface/type so consumers can import it and avoid using any in
useContext(FormContext) calls.

In `@src/hooks/useForm.ts`:
- Around line 18-20: handleChange and handleSubmit are recreated each render
causing potential child re-renders; wrap them in React.useCallback to stabilize
references. Update handleChange to useCallback((name, value) => setValues(prev
=> ({ ...prev, [name]: value })), [setValues]) and memoize handleSubmit
similarly with useCallback, including its dependencies (e.g., values, onSubmit
or any validation functions) so the returned handlers from the hook remain
stable when passed through FormProvider.

In `@src/hooks/useModal.ts`:
- Around line 5-15: Update the JSDoc for the useModal hook to accurately reflect
its behavior: remove references to "ESC로 닫기" and "outside click 감지", and instead
document that it manages open/close state and handles Android hardware back
button behavior (with outside click handled in Modal.tsx); reference the hook
name useModal and the Modal.tsx component so maintainers know where
outside-click logic lives.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b643a98d-5ccc-42e2-b1aa-1b0dd5c2df03

📥 Commits

Reviewing files that changed from the base of the PR and between 218ea39 and 27a58d3.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • src/components/Button/Button.tsx
  • src/components/Dropdown/Dropdown.tsx
  • src/components/Input/Input.tsx
  • src/components/Loading/Loading.tsx
  • src/components/Modal/Modal.tsx
  • src/components/Skeleton/Skeleton.tsx
  • src/components/common/Button.tsx
  • src/components/common/Input.tsx
  • src/contexts/FormContext.tsx
  • src/hooks/useDropdown.ts
  • src/hooks/useForm.ts
  • src/hooks/useInfiniteScroll.ts
  • src/hooks/useModal.ts
  • src/hooks/useToggle.ts
  • src/utils/validation.ts
💤 Files with no reviewable changes (2)
  • src/components/common/Button.tsx
  • src/components/common/Input.tsx

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
src/contexts/FormContext.tsx (1)

32-33: ⚠️ Potential issue | 🟡 Minor

Guard undefined context too, not only null.

At Line 32, === null misses cases where FormProvider passes undefined as value; consumers (e.g., Input) can then crash during destructuring. Use a nullish check.

💡 Proposed fix
 export const useFormContext = () => {
   const context = useContext(FormContext);
-  if (context === null) {
+  if (context == null) {
     throw new Error('useFormContext must be used within a FormProvider');
   }
   return context;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/contexts/FormContext.tsx` around lines 32 - 33, The null-check in
useFormContext only tests for === null and misses undefined values; update the
guard in useFormContext to use a nullish check (e.g., context == null or context
=== null || context === undefined) so it throws when the context is null or
undefined, ensuring consumers like Input that destructure the context won't
crash; locate the useFormContext function and the FormProvider value usage and
replace the strict null check with a nullish check to cover both cases.
🧹 Nitpick comments (1)
src/contexts/FormContext.tsx (1)

18-21: Replace any with an explicit FormContext contract.

At lines 18 and 20, using any removes compile-time guarantees for the { values, errors, handleChange } shape consumed in src/components/Input/Input.tsx (line 20). The Input component destructures and uses these properties:

  • values[name] — string value access
  • errors[name] — string or falsy error access
  • handleChange(name, text) — called with string name and string value

Strong typing here will prevent silent shape drift and catch mismatches at compile time.

♻️ Proposed typed refactor
-import React, { createContext, useContext } from 'react';
+import React, { createContext, useContext } from 'react';
+
+type FormContextValue = {
+  values: Record<string, string>;
+  errors: Record<string, string | undefined>;
+  handleChange: (name: string, value: string) => void;
+};
+
+type FormProviderProps = {
+  children: React.ReactNode;
+  value: FormContextValue;
+};

-const FormContext = createContext<any>(null);
+const FormContext = createContext<FormContextValue | null>(null);

-export const FormProvider = ({ children, value }: any) => {
+export const FormProvider = ({ children, value }: FormProviderProps) => {
   return <FormContext.Provider value={value}>{children}</FormContext.Provider>;
 };

-export const useFormContext = () => {
+export const useFormContext = (): FormContextValue => {
   const context = useContext(FormContext);
-  if (context === null) {
+  if (context == null) {
     throw new Error('useFormContext must be used within a FormProvider');
   }
   return context;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/contexts/FormContext.tsx` around lines 18 - 21, Replace the loose any
types on FormContext and FormProvider with a concrete interface describing the
form contract used by Input: declare a FormContextType with values:
Record<string,string>, errors: Record<string,string|undefined|false>, and
handleChange: (name: string, text: string) => void, then use
createContext<FormContextType | null>(null) (or provide a safe default) and type
the FormProvider props as { children: React.ReactNode; value: FormContextType }
so consumers like Input (which reads values[name], errors[name], and calls
handleChange(name, text)) get compile-time guarantees.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/contexts/FormContext.tsx`:
- Around line 32-33: The null-check in useFormContext only tests for === null
and misses undefined values; update the guard in useFormContext to use a nullish
check (e.g., context == null or context === null || context === undefined) so it
throws when the context is null or undefined, ensuring consumers like Input that
destructure the context won't crash; locate the useFormContext function and the
FormProvider value usage and replace the strict null check with a nullish check
to cover both cases.

---

Nitpick comments:
In `@src/contexts/FormContext.tsx`:
- Around line 18-21: Replace the loose any types on FormContext and FormProvider
with a concrete interface describing the form contract used by Input: declare a
FormContextType with values: Record<string,string>, errors:
Record<string,string|undefined|false>, and handleChange: (name: string, text:
string) => void, then use createContext<FormContextType | null>(null) (or
provide a safe default) and type the FormProvider props as { children:
React.ReactNode; value: FormContextType } so consumers like Input (which reads
values[name], errors[name], and calls handleChange(name, text)) get compile-time
guarantees.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1de04049-d580-4e3e-82b3-768cfe7506b8

📥 Commits

Reviewing files that changed from the base of the PR and between 27a58d3 and ac80a23.

📒 Files selected for processing (5)
  • src/components/Button/Button.tsx
  • src/contexts/FormContext.tsx
  • src/hooks/useForm.ts
  • src/hooks/useInfiniteScroll.ts
  • src/utils/validation.ts
✅ Files skipped from review due to trivial changes (2)
  • src/utils/validation.ts
  • src/hooks/useInfiniteScroll.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/Button/Button.tsx
  • src/hooks/useForm.ts

@jung518 jung518 merged commit 45c0933 into dev Apr 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature 새로운 기능 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant