티스토리 뷰
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-form
이 input
값을 직접 제어하지 못하고 있어서
발생하는 문제였다.
그래서 그냥 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 |
- Total
- Today
- Yesterday
- Warning: A component is changing an uncontrolled input to be controlled.
- Warning: Each child in a list should have a unique "key" prop.
- Warning: validateDOMNesting(...): <li> cannot appear as a descendant of <li>
- Fetch와 Axios 의 장단점
- axios 설치하기
- 에러모음집
- readme작성해보기
- readme 역할
- styled component 조건부 사용방법
- 별점 색채우기
- readme 이미지 추가 방법
- nextjs 토큰 만료처리하기
- axios 사용하기
- 유효성검사
- 영화별점만들기
- styled component 사용방법
- git cache
- 영화 별점
- simple Icon 사용방법
- readme 작성해야 하는 이유
- readme 작성 방법
- axios CRUD
- styled component 설치방법
- axiosinstance 사용 시 토큰 사용 법
- axios instance 작성하기
- 별점만들기
- styled component GlobalStyle 사용방법
- 유효성검사 css
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |