ChamomileGuides 3.0.4 Help

컴포넌트 기능 설명

4.1 useGetQuery

useGetQuery Hook Guide

Introduction

useGetQuery는 Tanstack Query(React Query)의 useQuery 훅을 래핑한 커스텀 훅입니다. queryKey와 endpoint를 받아 데이터를 가져오고, 캐싱 및 신선도 관리를 쉽게 할 수 있도록 도와줍니다. gcTime과 staleTime의 기본값을 설정하여 사용자가 필요에 따라 오버라이드할 수 있도록 합니다.

Installation

먼저, 필요한 패키지를 설치합니다:

npm install axios @tanstack/react-query

또는

yarn add axios @tanstack/react-query

Usage

const ExampleComponent = () => { const { data, error, isLoading } = useGetQuery<IQueryResult> { queryKey: ['menuAuthList', searchParamUri], endpoint: `/chmm/menu-auth/list?${searchParamUri}&size=300`, }; if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <h1>Data:</h1> <pre>{JSON.stringify(data.data, null, 2)}</pre> </div> ); };

API

Parameters

queryKey

  • Type: string | unknown[]

  • Description: Tanstack Query의 키로 사용됩니다. 이 키는 캐시된 데이터를 식별하는 데 사용되며, 동일한 queryKey를 가진 쿼리는 동일한 데이터를 공유합니다. queryKey는 단일 문자열 또는 배열 형태로 정의할 수 있습니다.

  • Usage:

    • 단일 문자열:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', });
    • 배열 형태:

      const { data } = useGetQuery({ queryKey: ['user', userId], endpoint: `/api/users/${userId}`, });
  • Best Practices:

    • Unique Keys: 각 쿼리는 고유한 queryKey를 가져야 합니다. 동일한 키를 사용하면 데이터가 충돌하거나 덮어씌워질 수 있습니다.

    • Descriptive Keys: queryKey는 가능한 한 설명적이어야 합니다. 예를 들어, ['user', userId]userId에 해당하는 사용자의 데이터를 가져오는 쿼리임을 명확히 합니다.

    • Stable Keys: queryKey는 안정적이어야 하며, 컴포넌트가 리렌더링될 때마다 변경되지 않아야 합니다. 예를 들어, 객체를 키로 사용하는 경우 객체의 참조가 변경되지 않도록 주의해야 합니다.

  • Warings:

    • Dynamic Keys: 동적 키를 사용할 때는 키의 순서와 타입이 일관되게 유지되어야 합니다. 예를 들어, ['user', userId]['user', anotherUserId]는 동일한 구조를 가져야 합니다.

    • Avoid Non-Serializable Keys: queryKey는 직렬화 가능한 값이어야 합니다. 함수나 클래스 인스턴스와 같은 비직렬화 가능한 값을 키로 사용하지 않도록 합니다.

endpoint

  • Type: string

  • Description: 데이터를 가져올 API 엔드포인트입니다. 이 엔드포인트는 axiosInstance를 통해 호출됩니다.

  • Usage:

    const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', });

gcTime

  • Type: number (optional)

  • Description: 데이터가 메모리에 유지되는 시간입니다. 기본값은 5분(300,000ms)입니다. 이 시간이 지나면 데이터는 가비지 컬렉션에 의해 메모리에서 제거됩니다.

  • Usage:

    const { data } = useGetQuery({ queryKey: 'comments', endpoint: '/api/comments', gcTime: 10 * 60 * 1000, // 10분 });

staleTime

  • Type: number (optional)

  • Description: 데이터가 신선한 상태로 간주되는 시간입니다. 기본값은 0입니다. 이 시간 동안에는 재요청을 하지 않고 캐시된 데이터를 사용합니다.

  • Usage:

    const { data } = useGetQuery({ queryKey: 'todos', endpoint: '/api/todos', staleTime: 5 * 60 * 1000, // 5분 });

...rest

  • Type: object (optional)

  • Description: Tanstack Query의 useQuery 훅에 전달할 추가 옵션입니다. 이 옵션들은 Tanstack Query의 다양한 기능을 활용할 수 있도록 도와줍니다.

Common Options
  • enabled:

    • Type: boolean

    • Description: 쿼리가 활성화될지 여부를 결정합니다. false로 설정하면 쿼리가 자동으로 실행되지 않습니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', enabled: isUserLoggedIn, // 쿼리를 조건부로 활성화 });
  • refetchOnWindowFocus:

    • Type: boolean

    • Description: 사용자가 브라우저 창을 다시 포커스할 때 쿼리를 다시 가져올지 여부를 결정합니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', refetchOnWindowFocus: true, // 창 포커스 시 재요청 });
  • refetchOnMount:

    • Type: boolean

    • Description: 컴포넌트가 마운트될 때 쿼리를 다시 가져올지 여부를 결정합니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', refetchOnMount: false, // 마운트 시 재요청하지 않음 });
  • refetchOnReconnect:

    • Type: boolean

    • Description: 네트워크가 다시 연결될 때 쿼리를 다시 가져올지 여부를 결정합니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', refetchOnReconnect: true, // 네트워크 재연결 시 재요청 });
  • retry:

    • Type: boolean | number

    • Description: 쿼리 실패 시 재시도 횟수를 설정합니다. false로 설정하면 재시도하지 않습니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', retry: 3, // 최대 3번 재시도 });
  • cacheTime:

    • Type: number

    • Description: 데이터가 캐시에 유지되는 시간입니다. 이 시간이 지나면 데이터는 가비지 컬렉션에 의해 메모리에서 제거됩니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'comments', endpoint: '/api/comments', cacheTime: 10 * 60 * 1000, // 10 minutes });
  • onSuccess:

    • Type: (data: TData) => void

    • Description: 쿼리가 성공적으로 완료되었을 때 호출되는 콜백 함수입니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', onSuccess: (data) => { console.log('Data fetched successfully:', data); }, });
  • onError:

    • Type: (error: TError) => void

    • Description: 쿼리가 실패했을 때 호출되는 콜백 함수입니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', onError: (error) => { console.error('Error fetching data:', error); }, });
  • select:

    • Type: (data: TData) => TSelectedData

    • Description: 쿼리 데이터에서 특정 부분만 선택하여 반환할 수 있는 함수입니다.

    • Usage:

      const { data } = useGetQuery({ queryKey: 'posts', endpoint: '/api/posts', select: (data) => data.posts, // 데이터의 특정 부분만 선택 });

이 외에도 Tanstack Query의 useQuery 훅에서 제공하는 다양한 옵션들을 rest 파라미터에 포함시킬 수 있습니다.

자세한 내용은 Tanstack Query 공식 문서를 참고하세요.

4.2 useMutationQuery

useMutationQuery Hook Guide

Introduction

useMutationQuery는 Tanstack Query의 useMutation 훅을 래핑한 커스텀 훅입니다. queryKey, endpoint, method를 받아 데이터를 변경하고, 변경된 데이터를 기반으로 쿼리를 무효화하여 최신 데이터를 가져올 수 있도록 도와줍니다.

Installation

먼저, 필요한 패키지를 설치합니다:

npm install axios @tanstack/react-query

또는

yarn add axios @tanstack/react-query

Usage

import { useMutationQuery } from '@/hooks/useMutationQuery'; const ExampleComponent = () => { const mutation = useMutationQuery({ queryKey: ['menuAuthList'], endpoint: '/chmm/menu/create', method: 'POST', }); const handleSubmit = async () => { try { await mutation.mutateAsync({ key: 'value' }); console.log('Data submitted successfully'); } catch (error) { console.error('Error submitting data:', error); } }; return ( <div> <button onClick={handleSubmit}>Submit</button> </div> ); }; export default MyComponent;

API

Parameters

queryKey

  • Type: string | unknown[]

  • Description: Tanstack Query의 키로 사용됩니다. 이 키는 캐시된 데이터를 식별하는 데 사용되며, 동일한 queryKey를 가진 쿼리는 동일한 데이터를 공유합니다.

    • Usage:

      const mutation = useMutationQuery({ queryKey: ['user', userId], endpoint: `/api/users/${userId}`, method: 'PUT', });

endpoint

  • Type: string

  • Description: 데이터를 변경할 API 엔드포인트입니다. 이 엔드포인트는 axiosInstance를 통해 호출됩니다.

    • Usage:

      const mutation = useMutationQuery({ queryKey: 'posts', endpoint: '/api/posts', method: 'POST', });

method

  • Type string ('POST' | 'PUT' | 'DELETE')

  • Description: 데이터를 변경할 HTTP 메서드입니다.

    • Usage:

      const mutation = useMutationQuery({ queryKey: 'comments', endpoint: '/api/comments', method: 'DELETE', });

...rest

  • Type: object (optional)

  • Description: Tanstack Query의 useMutation 훅에 전달할 추가 옵션입니다. 이 옵션들은 Tanstack Query의 다양한 기능을 활용할 수 있도록 도와줍니다.

Common Options
  • mutationKey:

    • Type: string | unknown[]

    • Description: 뮤테이션을 식별하는 키입니다. 이 키는 캐시된 뮤테이션 데이터를 식별하는 데 사용됩니다.

    • Usage:

      const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', mutationKey: 'createPost', });
  • onMutate:

    • Type: (variables: TVariables) => Promise<unknown> | unknown

    • Description: 뮤테이션이 시작될 때 호출되는 함수입니다. 이 함수는 뮤테이션이 발생하기 전에 실행되며, 낙관적 업데이트를 설정하거나 캐시를 업데이트하는 데 사용할 수 있습니다.

    • Usage:

      const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', onMutate: (variables) => { console.log('Mutation started with variables:', variables); }, });
    • onSuccess:

      • Type: (data: TData, variables: TVariables, context: unknown) => void

      • Description: 뮤테이션이 성공적으로 완료되었을 때 호출되는 함수입니다. 이 함수는 서버에서 반환된 데이터와 함께 호출되며, 성공적인 응답을 처리하는 데 사용할 수 있습니다.

      • Usage:

        const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', onSuccess: (data) => { console.log('Mutation successful with data:', data); }, });
    • onError:

      • Type: (error: TError, variables: TVariables, context: unknown) => void

      • Description: 뮤테이션이 실패했을 때 호출되는 함수입니다. 이 함수는 발생한 에러와 함께 호출되며, 에러를 처리하는 데 사용할 수 있습니다.

      • Usage:

        const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', onError: (error) => { console.error('Mutation failed with error:', error); }, });
    • onSettled:

      • Type: (data: TData | undefined, error: TError | null, variables: TVariables, context: unknown) => void

      • Description: 뮤테이션이 성공 또는 실패 후에 항상 호출되는 함수입니다. 이 함수는 뮤테이션의 결과와 상관없이 호출되며, 후속 처리를 수행하는 데 사용할 수 있습니다.

      • Usage:

        const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', onSettled: (data, error) => { console.log('Mutation settled with data:', data, 'and error:', error); }, });
    • retry:

      • Type: boolean | number | (failureCount: number, error: TError) => boolean | number

      • Description: 뮤테이션이 실패했을 때 재시도할 횟수를 설정합니다. false로 설정하면 재시도하지 않습니다. 함수로 제공하면 재시도 여부를 동적으로 결정할 수 있습니다.

      • Usage:

        const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', retry: 3, // 최대 3번 재시도 });
    • retryDelay:

      • Type: number | (failureCount: number, error: TError) => number

      • Description: 재시도 사이의 지연 시간을 설정합니다. 기본값은 지수 백오프입니다. 함수로 제공하면 지연 시간을 동적으로 결정할 수 있습니다.

      • Usage:

        const mutation = useMutationQuery({ queryKey: 'myData', endpoint: '/api/my-endpoint', method: 'POST', retryDelay: 1000, // 1초 지연 후 재시도 });

이 외에도 Tanstack Query의 useMutation 훅에서 제공하는 다양한 옵션들을 rest 파라미터에 포함시킬 수 있습니다.

자세한 내용은 Tanstack Query 공식 문서를 참고하세요.

4.3 useGetFile

useGetFile Hook Guide

Introduction

useGetFile는 Tanstack Query(React Query)의 useQuery 훅을 래핑하여 파일 데이터를 가져오는 커스텀 훅입니다. 이 훅은 주어진 엔드포인트에서 파일 데이터를 가져오는 데 특화된 훅입니다. 가져온 데이터를 캐시하여 일정 시간(기본 1시간) 동안 재사용할 수 있도록 도와줍니다.

Installation

먼저, 필요한 패키지를 설치합니다:

npm install axios @tanstack/react-query

또는

yarn add axios @tanstack/react-query

Usage

const ExampleComponent = () => { const { data, error, isLoading, refetch } = useGetFile<BlobPart>({ queryKey: ['fileDownload', downloadFileEndPoint], endpoint: downloadFileEndPoint, enabled: !!downloadFileEndPoint, }); const [file, setFile] = useState<File | null>(); const handleDownload = () => { refetch(); }; useEffect(() => { if (!data) return; const fileObject = makeFileFromResponse(data); setFile(fileObject); }, [data, setFile]); return ( <div> <button onClick={handleDownload}>Download File</button> {isLoading && <p>Loading...</p>} {error && <p>Error: {error.message}</p>} {data && ( <a href={URL.createObjectURL(data.data)} download="my-file"> Download Link </a> )} </div> ); };

API

Parameters

queryKey

  • Type: string | unknown[]

  • Description: Tanstack Query의 키로 사용됩니다. 이 키는 캐시된 데이터를 식별하는 데 사용되며, 동일한 queryKey를 가진 쿼리는 동일한 데이터를 공유합니다. 다운로드할 파일이 있는 주소를 배열에 넣어줍니다

  • Usage:

    const { data } = useGetFile({ queryKey: ['file', fileId], endpoint: `/api/files/${fileId}`, });

endpoint

  • Type: string

  • Description: 데이터를 가져올 API 엔드포인트입니다. 이 엔드포인트는 axiosInstance를 통해 호출됩니다.

useGetQuery와 차이점

  • Purpose: useGetQuery는 일반적인 데이터를 가져오는데 사용되는 훅이며, useGetFile은 파일 데이터를 가져오는데 특화된 훅입니다.

  • Response Type: useGetFileresponseType: 'blob'을 사용하여 파일 데이터를 처리하고, useGetQuery는 기본적으로 JSON 형식을 처리합니다.

4.4 File Upload

File Upload Guide

Introduction

파일업로드는 <FileUploadButton /> 공통 컴포넌트를 통해 버튼 스타일과 로직이 함께 구현되어 있습니다.

<FileUploadButton />는 파일명이 보이는 텍스트 필드와 업로드 버튼, 다운로드 버튼이 한꺼번에 있는 <FileInput /> 내부에서 사용됩니다.

파일 객체 자체를 서버로 보낼때는 각 화면에 해당하는 수정/저장 API에 File 객체를 넣어 전달하면 됩니다.

Usage

const FileUploadExample = () => { const [file, setFile] = useState<IFile | null | undefined>(); return <FileUploadButton setFile={setFile} acceptedFileTypes=".pdf" maxFileSize={[1024, 'MB']} />; };
const FileInputExample = () => { const [file, setFile] = useState<IFile | null | undefined>(); // acceptedFileTypes, maxFileSize가 있는 경우 가이드라인에 업로드 허용 확장자와 최대 사이즈에 대한 가이드라인이 하단에 자동으로 나타납니다. const guideLines = ['파일은 최대 한개만 업로드 가능합니다.']; return ( <FileInput isReadOnly={false} file={file} setFile={setFile} acceptedFileTypes={'.xlsx'} maxFileSize={[900, 'MB']} guideLines={guideLines} /> ); };

API

Parameters

setFile

  • Type: Dispatch<SetStateAction<File | null | undefined>>

  • Description: 파일 상태를 설정하는 state 함수를 전달해줍니다

  • setFile을 통해 넘겨진 File객체는 { flag: 'I' }를 가지고 있어 기존 파일과 구분할 수 있습니다.

acceptedFileTypes

  • Type: string (optional)

  • Description: 파일 업로드 시 허용 확장자 타입을 ,로 구분하여 한 줄에 넘겨줍니다.

maxFileSize

  • Type: [number, 'B' | 'KB' | 'MB' | 'GB'] (optional)

  • Description: 파일 업로드 시 최대 크기를 설정해줍니다. 최대 크기를 넘어가면 파일 크기를 초과했다는 Toast 메세지가 나타납니다.

업로드 로직

  1. 상태 선언

  • useState 훅을 사용하여 file이라는 상태 변수를 선언합니다.

    const [file, setFile] = useState<IFile | null | undefined>();
    • file의 타입은 IFile | null | undefined로 정의되어 있습니다.

      • IFile: 파일 객체를 나타내는 사용자 정의 타입입니다.

      • null: 파일이 없음을 의미합니다.

      • undefined: 초기 상태 또는 파일이 아직 아직 설정되지 않은 상태를 의미합니다.

    • setFilefile상태를 업데이트하는 함수입니다.

  1. 컴포넌트 사용

  • setFile 함수를 FileUploadButton 컴포넌트의 setFile prop으로 전달합니다.

    <FileUploadButton setFile={setFile} />
    • 이는 FileUploadButton 컴포넌트가 파일 업로드 이벤트가 발생했을 때 setFile 함수를 호출하여 file 상태를 업데이트할 수 있도록 합니다.

4.5 File Download

File Download Guide

Introduction

파일 다운로드는 <FileDownloadButton /> 공통 컴포넌트를 통해 버튼 스타일과 로직이 함께 구현되어 있습니다.

<FileDownloadButton />는 파일명이 보이는 텍스트 필드와 업로드 버튼, 다운로드 버튼이 한꺼번에 있는 <FileInput /> 내부에서 사용됩니다.

Usage

const FileDownloadExample = () => { const [file, setFile] = useState<IFile | null | undefined>(); const endpoint = '파일 다운로드 주소'; return <FileDownloadButton file={file} setFile={setFile} downloadFileEndPoint={endpoint} />; };
const FileInputExample = () => { const [file, setFile] = useState<IFile | null | undefined>(); // acceptedFileTypes, maxFileSize가 있는 경우 가이드라인에 업로드 허용 확장자와 최대 사이즈에 대한 가이드라인이 하단에 자동으로 나타납니다. const guideLines = ['파일 이름에는 특수문자를 포함하지 마세요.']; const endpoint = '파일 다운로드 주소'; return ( <FileInput isReadOnly={false} file={file} setFile={setFile} acceptedFileTypes={'.png, .image, .img'} guideLines={guideLines} maxFileSize={[500, 'MB']} downloadFileEndPoint={endpoint} /> ); };

API

Parameters

file

  • Type: File | null | undefined

  • Description: 파일 업로드를 통해 input에서 가지고 있는 파일 객체, 다운로드를 통해. 가지고 있는 파일 객체를 나타냅니다.

setFile

  • Type: Dispatch<SetStateAction<File | null | undefined>>

  • Description: 파일 상태를 설정하는 state 함수를 전달해줍니다

  • 파일 다운로드 버튼 클릭 setFile을 이용해 file 객체가 저장됩니다.

  • downloadFileEndPoint 파일 다운로드 주소가 있어야 다운로드 버튼이 활성화 됩니다.

downloadFileEndPoint

  • Type: string (optional)

  • Description: 파일 다운로드 API 주소로 downloadFileEndPoint가 있어야 파일 다운로드 API를 호출합니다.

다운로드 로직

FileDownloadButton 컴포넌트의 다운로드 로직은 파일이 이미 존재하는지 확인하고, 존재하지 않으면 파일을 가져와서 다운로드하는 과정을 포함합니다.

아래는 파일 다운로드 버튼 클릭 시 handleFileDownload함수 내부에 대한 상세 설명입니다.

  1. 파일 존재 여부 확인:

    • if (file) { ... } 블록에서 파일이 이미 존재하는지 확인합니다.

    • 파일이 존재하면 downloadFile(file)을 호출하여 파일을 다운로드합니다.

    • 파일 업로드 버튼을 통해 브라우저 상에서 파일을 업로드 한 경우, 파일 다운로드 쿼리를 호출하여 파일 객체를 가지고 있는 경우 해당됩니다.

  2. 파일이 존재하지 않는 경우:

    • if (!file) { ... } 블록에서 파일이 존재하지 않는 경우, refetch()를 호출하여 파일을 다시 가져옵니다.

    • refetch()는 비동기 함수로, 파일 데이터를 가져오는 쿼리 요청을 수행합니다.

  3. 파일 데이터 처리:

    • const response = await refetch();에서 refetch()의 응답을 기다립니다.

    • 응답 데이터가 존재하면, makeFileFromResponse(response.data)를 호출하여 응답 데이터를 파일 객체로 변환합니다.

    • 변환된 파일 객체를 setFile(fileObject)를 통해 상태에 저장합니다.

    • 변환된 파일 객체를 downloadFile(fileObject)를 호출하여 다운로드합니다.

  4. 에러 처리:

    • 에러가 발생하면 showToast('파일 다운로드 오류', 'error')를 호출하여 사용자에게 알림을 표시합니다.

4.6 Common Code

Common Code Guide

Introduction

공통코드는 useCommonCode훅과 <CommonCode /> 공통 컴포넌트를 이용하여 사용할 수 있습니다.

useCommonCode hook

useCommonCode는 Tanstack Query(React Query)의 useQuery 훅을 래핑한 커스텀 훅입니다.

공통코드의 데이터만 이용할때는 해당 훅을 사용하여 공통 코드의 데이터를 가져옵니다.

대분류 카테고리 아이디인 categoryId, 중분류 코드 아이디인 codeId, '전체' 옵션 제외 여부인 isExcludeAllOption를 파라미터로 받아 카테고리(코드)아이디를 모두 만족하는 공통코드 리스트 데이터를 반환합니다.

useCommonCode Usage

// '레벨'과 관련된 공통코드 데이터를 가져옵니다 const commonCodeMenuLevel = useCommonCode('G1', 'LEVEL'); // '사용여부'와 관련된 공통코드 데이터를 가져옵니다 const commonCodeUse = useCommonCode('G1', 'USE', true);

CommonCode Component

useCommonCode을 내부에서 사용하여 공통코드 데이터를 활용하여 select, radio, checkbox 컴포넌트로 만드는 공통 컴포넌트 입니다.

CommonCode API

CommonCode Parameters

categoryId, codeId, isExcludeAllOption

  • Description: useCommonCode훅에서 공통 코드 데이터를 가져오기 위해 필요한 파라미터 입니다.

placeHolder

  • Type: string (optional)

  • Description: select 컴포넌트의 placeHolder에 들어갈 텍스트를 전달해줍니다.

defaultValue

  • Type: string | string[] (optional)

  • Description: 컴포넌트들의 기본값을 전달해줍니다.

onValueChange

  • Type: () => void (optional)

  • Description: 값 변경 핸들러를 전달해줍니다.

CommonCode Usage

const ExampleComponent = () => { const handleChangeValue = (e) => { const selectedValue = e; }; return ( <div> <CommonCode type="select" categoryId="G1" codeId="APP_DEPLOY_PHASE" className="w-[150px]" placeHolder="앱 배포 단계" onValueChange={handleChangeSelect} /> <CommonCode categoryId="G1" codeId="APP_DEPLOY_PHASE" type="radio" isExcludeAllOption={true} defaultValue="item00001" onValueChange={handleChangeSelect} /> <CommonCode categoryId="G1" codeId="APP_DEPLOY_PHASE" type="checkbox" isExcludeAllOption={true} defaultValue={['item00002']} onValueChange={handleChangeSelect} /> </div> ); };
Last modified: 21 4월 2025