티스토리 뷰

input에서 readOnly 속성값을 true로 주고, 드롭다운으로 선택한 값을 유저에게 보여주어야 한다. 

 

드롭다운으로 보여주는 값은 enum 값이 별도로 존재하였고, enum을 유저에게 보여줄 값으로 변환해야한다. 

 

나의 상황을 순서로 정리해보자면 다음과 같다. 

1. input은 readOnly 속성으로 클릭했을 때 dropdown으로 값을 선택

2. dropdown에 들어갈 값은 enum 값이 존재. 

3. 유저에게 보여줄 때에는 enum 값을 유저에게 보여줄 값으로 변환 

 

아래는 enum 값, 유저에게 보여주어야할 값이다.

→ 타입을 사용하지 않고 enum을 사용한 이유가 있나? 

: 없다. type으로 코드를 작성했는데, 사수님이 type은 자료값에만 사용하고 현재와 같은 상황에서는 enum만 사용하라고 하셨다.

export enum UserJob {
    PRESIDENT = 'PRESIDENT',
    C_LEVEL = 'C_LEVEL',
    GA_LEADER = 'GA_LEADER',
    GA_MANAGER = 'GA_MANAGER',
    HR_LEADER = 'HR_LEADER',
    HR_MANAGER = 'HR_MANAGER',
    ETC = 'ETC',
}

export const USER_JOB_LABELS: Record<UserJob, string> = {
    [UserJob.PRESIDENT]: '대표',
    [UserJob.C_LEVEL]: '이사',
    [UserJob.GA_LEADER]: '총무 팀장',
    [UserJob.GA_MANAGER]: '총무 팀원',
    [UserJob.HR_LEADER]: '인사 팀장',
    [UserJob.HR_MANAGER]: '인사 팀원',
    [UserJob.ETC]: '기타',
};

 

 

아래는 문제가 되었던 코드

   // 선택된 값 담기
   const handleSelect = (job: UserJob) => {
        setValue('job', job);
        setIsActive(false);
    };
    
    // UserJob enum의 모든 값을 배열로 변환해 드롭다운 옵션으로 사용
    const jobOptions = Object.values(UserJob);


	// input 영역
	<input
    	type="text"
        readOnly
        value={value}
        onClick={() => {
        	setIsActive(!isActive);
        }}
        onBlur={(e) => {
        	registerOnBlur(e);
            if (!selectedJob) {
            	setIsActive(false);
            }
        }}
        onChange={(e) => {
        	registerOnChange(e);
        }}
        {...{ref, ...restRegister}}
        className="w-full bg-white h-14 cursor-pointer"
	/>
    
    {.. 생략}
    
    // dropdown 영역
    {isActive && (
    	<ul className="absolute z-10 bg-white border border-neutral-300 w-full mt-1 rounded-lg max-h-60 overflow-auto">
        	{jobOptions.map((job) => (
        		<li
        			key={job}
        			className="px-4 py-3 hover:bg-neutral-100 active:bg-primaryColor-900 active:text-white cursor-pointer text-14"
        			onMouseDown={() => {
        				handleSelect(job);
        			}}
        		>
        			{t_userJob(job)}
        		</li>
        	))}
    	</ul>
    )}

 

문제 1. → 처음 값을 클릭 했을 때 바로 반영이 되지 않음

문제 2. → 두번 째 클릭 후 값을 선택했을 때 값이 반영이 됨

문제 3. → 다른 input을 클릭하거나 다음 스텝 이동을 위해 버튼을 클릭하면 값이 초기화 됨.

 

※ setValue를 사용한 이유. 

→ API 요청 시 담아야 하는 값은 enum, 유저에게 보여주는 값은 변환된 값으로 유저가 클릭한 값을 바로 담으면 변환된 값이 담김.

 

 

문제 원인은 간단했다. 

 

input value를 관리하는 방식이 문제였다.

나의 코드는 value를 직접 관리하고 있다.

React-hook-forminput 값을 직접 제어하지 못하고 있어서 발생하는 문제였다.

 

그래서 그냥 React-hook-form은 값을 담은 용도로만 사용할 수 있도록 input에 hidden 속성을 추가로 주고, 
담긴 값은 react-hook-form에서 담은 값을 유저가 볼수 있도록 포멧을 해서 보여줄 수 있도록 변경했더니 문제가 아주 쉽게해결되었다. 

※ Controller를 사용해도 가능.

 

변경된 코드

    const handleSelect = (job: UserJob) => {
        setValue('job', job, {shouldValidate: true});
        setIsActive(false);
    };
    
    export const t_userJob = (status?: UserJob) => {
    	if (!status) return '';
    	return USER_JOB_LABELS[status] || '';
    };
    
    <input type="text" readOnly hidden {...register('job', {required: '하는 일을 선택해주세요.'})} />
		<div
			onClick={() => setIsActive(!isActive)}
			onBlur={(e) => {
				registerOnBlur(e);
				if (!selectedJob) {
					setIsActive(false);
				}
			}}
			className="w-full bg-white pt-6 h-14 cursor-pointer border border-neutral-300 text-sm text-neutral-900 rounded-lg pl-12 pr-5 focus:outline focus:outline-1 focus:outline-primaryColor-900"
		>
			{t_userJob(selectedJob)}
		</div>
        
        {..생략}
        
	{isActive && (
		<ul className="absolute z-10 bg-white border border-neutral-300 w-full mt-1 rounded-lg max-h-60 overflow-auto">
			{jobOptions.map((job) => (
				<li
					key={job}
					className="px-4 py-3 hover:bg-neutral-100 active:bg-primaryColor-900 active:text-white cursor-pointer text-14"
					onMouseDown={() => {
						handleSelect(job);
					}}
				>
					{t_userJob(job)}
				</li>
			))}
		</ul>
	)}

'내가 쓸 유용한 잡지식' 카테고리의 다른 글

Tailwind 사용 시 <progress> pseudo-element  (0) 2025.03.28
REST API  (2) 2024.10.17
Visual Studio 단축키  (0) 2024.10.13
HTML 텍스트 입력 시  (0) 2024.09.19
next/dynamic 코드를 분리해주자 ?  (0) 2024.08.15