-
반응형
티스토리와 같은 방식의 태그를 구현
Input Tag
onKeyDown함수를 활용하여 Enter와 Tab이 눌렀을때 input을 다시 빈값으로 초기화 해준다.
const [tag, setTag] = useState("") const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (e.key === "Enter" || e.key === "Tab") { e.preventDefault(); setTag(""); } }
우선 해시태그와 input으로 태그를 입력할 수 있도록 작성
<span>#</span> <input className="input_tag" placeholder="태그입력" maxLength={10} value={tag} onChange={(e) => setTag(e.target.value)} onKeyDown={onKeyDown} />
이후 css로 모양을 잡아준다.
.tag { display: flex; align-items: center; justify-content: center; padding: 3px; max-width: 400px; flex-wrap: wrap; span { color: #909090; } .input_tag { margin-left: 5px; border: none; &:focus { outline: none; } } }
Tag List
Enter 혹은 Tab을 눌렀을때 입력한 태그를 TagList에 값을 추가해준다.
const [tag, setTag] = useState("") const [tagList, setTagList] = useState<string[]>([]) const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (e.key === "Enter" || e.key === "Tab") { e.preventDefault(); setTagList((prev) => [...prev, tag]); setTag(""); } }
이후 tagList 의 길이가 0보다 클때 tag list를 보여준다.
그럼 태그입력 후 Enter혹은 Tab을 누를때마다 tagList에 값이 생성이 되고 입력한 태그가 보이게 된다.
filter를 활용하여 현재 x 버튼을 누르면 누른 index값을 제외하여 다시 리스트를 만들어서 넣어준다.
const onClickDelete = (index: number) => { const newTagList = tagList.filter((_, idx) => idx !== index); setTagList(newTagList); }
tagList.length > 0 && ( <div className="tag_list"> {tagList.map((tag, index) => ( <div className="tag_item" key={index}> <span>#</span> <span key={index} className="tag">{tag}</span> <div className="tag_delete" onClick={() => onClickDelete(index)}> <CloseIcon/> </div> </div> ))} </div> )
Problem
태그 기능을 구현하면서 한글을 입력하면 onKeyDown이 두번 실행되면서 이전 값이 추가로 들어가게 되었다.
ex) 안녕 -> #안녕 #녕 이런식으로 값이 들어가게 된다.
이는 IME 입력 방식이 원인이다. IME는 글자를 조합하여 문자를 반드는 방식이다.
더보기- 영어 입력: "Enter" 키를 누를 때 한 번만 onKeyDown이 실행됨.
- 한글 입력: "한" + "ㄱ" -> "한글" 같은 조합 과정이 있기 때문에 onKeyDown이 두 번 실행될 수 있음.
React에서는 onCompositionStart와 onCompositionEnd를 활용하면 IME 입력 중인지 감지할 수 있다.
이를 활용하여
Input 태그에 onCompositionStart와 End를 활용하여 현재 입력중인지를 판단한다.
<input className="input_tag" placeholder="태그입력" maxLength={10} value={tag} onChange={(e) => setTag(e.target.value)} onKeyDown={onKeyDown} onCompositionStart={() => setIsComposing(true)} onCompositionEnd={() => setIsComposing(false)} />
이후 입력중이 아닐때만 onKeyDown을 실행시켜준다.
const [isComposing, setIsComposing] = useState(false); const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (isComposing) return; if (e.key === "Enter" || e.key === "Tab") { e.preventDefault(); setTagList((prev) => [...prev, tag]); setTag(""); } }
728x90반응형'Front > React' 카테고리의 다른 글
[ Vite + React ] i18n 언어 변경 기능 구현하기 (0) 2025.05.06 [ Vite + React ] React Router 사용 및 관리 (0) 2025.05.01 [ Vite + React ] Color Picker (0) 2025.02.28 [ Vite + React ] 절대경로 alias 설정하기 (0) 2025.02.28 [ Vite + React ] Timer 만들기 (0) 2024.12.10