자동완성 기능

miin·2023년 9월 18일
0

Skill Collection [Function]

목록 보기
39/46
post-thumbnail
  • state
 const [isOpenList, setIsOpenList] = useState<boolean>(false) //자동완성 오픈 상태
  const [autoList, setAutoList] = useState<string[]>([]) //자동완성 리스트
  const [cursorIdx, setCursorIdx] = useState<number>(-1) //키보드 방향으로 드롭다운 선택을 위한 상태
  const dropdownRef = useRef<React.LegacyRef<HTMLUListElement> | undefined>()
  • function
  const onChangeHandler = (e: ChangeEvent<HTMLInputElement>) => {
        const { value } = e.target

    setCategoryValue({
      ...categoryValue,
      categoryName: value,
    })

    if (value === '') {
      setAutoList([])
    } else {
      setAutoList(ITEM_CREATE_TITLE_LIST.filter((e) => e.includes(value)))
    }

    if (autoList.length > 0) {
      setIsOpenList(true)

      if (e.key === 'ArrowDown' && cursorIdx <= autoList.length - 2) {
        setCursorIdx((idx) => idx + 1)
      } else if (e.key === 'ArrowUp' && cursorIdx !== -1) {
        setCursorIdx((idx) => idx - 1)
      } else if (e.key === 'Enter' && cursorIdx !== -1) {
        setCategoryValue({
          ...categoryValue,
          categoryName: dropdownRef.current.children[cursorIdx].innerText,
        })

        setIsOpenList(false)
      }
    }
}
  • return
			<div
                style={{
                  display: 'flex',
                  flexDirection: 'column',
                  gap: '16px',
                  position: 'relative',
                }}
              >
                <InputComponent
                  ph="카테고리명을 입력"
                  style={inputStyle}
                  onChange={(e) => onChangeHandler(e)}
                  type="text"
                  name="categoryName"
                  value={categoryName}
                  onKeyUp={(e) => onChangeHandler(e)}
                />
          {isOpenList && (
                <Automatic ref={dropdownRef}>
                  {autoList.map((list, idx) => (
                    <AutomaticItem
                      key={list}
                      onKeyUp={() => autoHandler(list)}
                      color={idx === cursorIdx}
                    >
                      {list}
                    </AutomaticItem>
                  ))}
                </Automatic>
			)}
			</div>
  • style
const Automatic = styled.ul`
  position: absolute;
  top: 52px;
  left: 0;
  z-index: 91;
  width: 80%;
  /* border: 1px solid #c4c4c4; */
  background-color: white;
  border-radius: 16px;
`
const AutomaticItem = styled.li<{ color: boolean }>`
  height: 50px;
  padding: 14px 16px 14px 16px;
  font-size: 14px;
  border-right: 1px solid #c4c4c4;
  border-left: 1px solid #c4c4c4;
  border-bottom: 1px solid #c4c4c4;
  background-color: ${({ color }) => (color ? 'gray' : 'white')};

  &:first-child {
    border-radius: 16px 16px 0 0;
  }

  &:last-child {
    border-radius: 0 0 16px 16px;
  }

  &:hover {
    background-color: gray;
  }
`

0개의 댓글