[React] 자동완성 컴포넌트 Autocomplete Component

Tai Song·2022년 7월 4일
0

React

목록 보기
1/5

의사 코드

1. useState를 사용해 input값을 저장한다.
2. array 메소드인 filter로 입력된 input값을 포함한 요소들만 배열로 리턴한다.
3. array 메소드인 map으로 필터링된 배열을 드롭다운 형태로 렌더링 한다.

먼저, 훅(useState, useEffect)과 CSS용 스타일 컴포넌트를 불러온다.

import { useState, useEffect } from 'react';
import styled from 'styled-components';

styled-components 영역

const boxShadow = '0 4px 6px rgb(32 33 36 / 28%)';
const activeBorderRadius = '1rem 1rem 0 0';
const inactiveBorderRadius = '1rem 1rem 1rem 1rem';

export const InputContainer = styled.div`
  margin-top: 8rem;
  background-color: #ffffff;
  display: flex;
  flex-direction: row;
  padding: 1rem;
  border: 1px solid rgb(223, 225, 229);
  border-radius: ${inactiveBorderRadius};
  z-index: 3;
  box-shadow: 0;

  &:focus-within {
    box-shadow: ${boxShadow};
  }

  > input {
    flex: 1 0 0;
    background-color: transparent;
    border: none;
    margin: 0;
    padding: 0;
    outline: none;
    font-size: 16px;
  }

  > div.delete-button {
    cursor: pointer;
  }
`;

export const DropDownContainer = styled.ul`
  background-color: #ffffff;
  display: block;
  margin-left: auto;
  margin-right: auto;
  list-style-type: none;
  margin-block-start: 0;
  margin-block-end: 0;
  margin-inline-start: 0px;
  margin-inline-end: 0px;
  padding-inline-start: 0px;
  margin-top: -1px;
  padding: 0.5rem 0;
  border: 1px solid rgb(223, 225, 229);
  border-radius: 0 0 1rem 1rem;
  box-shadow: ${boxShadow};
  z-index: 3;

  > li {
    padding: 0 1rem;

    &.selected {
      background-color: lightgray;
    }
  }
`;

자동 완성을 위한 요소들을 넣은 배열을 선언한다.

const deselectedOptions = [
  'rustic',
  'antique',
  'vinyl',
  'vintage',
  'refurbished',
  '신품',
  '빈티지',
  '중고A급',
  '중고B급',
  '골동품'
];

자동 완성 구현 영역

export const Autocomplete = () => {
  const [hasText, setHasText] = useState(false);
  // input에 입력값이 존재하는지 확인하는 용도
  const [inputValue, setInputValue] = useState('');
  // 입력 받은 input값을 저장하는 용도
  const [options, setOptions] = useState(deselectedOptions);
  // 자동완성으로 보여줄 값들을 저장하는 용도

  useEffect(() => {
    if (inputValue === '') {
      setHasText(false);
      setOptions([]);
    } else {
      setOptions(deselectedOptions.filter((option) => {
        return option.includes(inputValue)
      }))
    }
  }, [inputValue]);
  // input을 입력할 때마다, input을 포함(includes)한 요소들만 모아 options 배열 업데이트

  const handleInputChange = (event) => {
    setInputValue(event.target.value);
    setHasText(true);
  };
  // input의 onChange 이벤트 때, 입력값을 inputValue에 저장하고 hasText값 갱신

  const handleDropDownClick = (clickedOption) => {
    setInputValue(clickedOption);
  };
  // 보여지는 자동완성 값 중 하나를 클릭하면 해당 값이 input에 할당

  const handleDeleteButtonClick = (event) => {
    setInputValue('');
  };
  // 삭제 버튼을 누르면, inputValue를 초기화

  return (
    <div className='autocomplete-wrapper'>
      <InputContainer>
        <input onChange={handleInputChange} value={inputValue}></input>
        <div className='delete-button' onClick={handleDeleteButtonClick}>&times;</div>
      </InputContainer>
      {hasText && <DropDown options={options} handleComboBox={handleDropDownClick} />}
      // 입력된 텍스트가 있을 때만 드롭다운이 보여지도록 조건 설정
      // 하지 않을 시, 아무 것도 입력하지 않은 상태에서도 드롭다운이 보여짐
    </div>
  );
};

/* 자동완성 배열(options)에 들어간 값들이 드롭다운으로 보여지는 부분 */
export const DropDown = ({ options, handleComboBox, selected }) => {
  return (
    <DropDownContainer>
      {options.map((option, index) => {
        return (
          <li key = {index}
          onClick = {() => handleComboBox(option)}>
            {option}
          </li>
        )
      })}
    </DropDownContainer>
  );
};
```
profile
Read The Fucking MDN

0개의 댓글