TRACK1 리팩토링 이야기, Hashtags


Hashtags 기능 과정

  1. Hashtags가 생성되었을 때, style과 <div>를 생성한다.
  2. input창과 style을 지정한다.
  3. input에 onKeyDown을 통해 엔터시 발생하는 함수를 작성한다.

(?) onKeyDown이란?

  • event 매개변수를 통해 이벤트 객체에 접근

  • event.key를 통해 눌린 키의 값을 확인

  • event.keyCode를 사용하여 키보드 키의 코드 확인

  1. onKeyDown 함수 이름을 handleTag라고 하자.
  • event.key를 통해 Enter가 아닌 경우, return 해준다. (함수를 빠져나온다.)
  • input창에 들어오는 value값을 trim()하여 공백을 모두 제거해주었을 때, value이 없다면, 또 return해준다. (함수를 빠져나온다.)
  • hashtag text를 담는 state 배열에 input 창에 들어오는 value를 담는데, 이전에 작성한 hashtagText들도 함께 담아 주는 것이 포인트이다.

` setHashtagText([…hashtagText, value]);`

  • value를 ‘’ 빈 값으로 만들어주어 input의 값을 초기화 시켜준다.
  1. map 함수를 통해 hashtagText 배열을 화면에 띄워준다.

[ 전체 코드 ]


return (
  const [hashtagText, setHashtagText] = useState<string[]>([]);

function handleEnterHashtag(e: KeyboardEvent<HTMLInputElement>) {
    if (e.key !== "Enter") return;
    const value = (e.target as HTMLInputElement).value;
    if (!value.trim()) return;
    setHashtagText([...hashtagText, value]);
    (e.target as HTMLInputElement).value = "";
setHashtagLength(0); // 이건 아래 동적 width값 설정의 초기화를 위한 코드임. 
  }

 {hashtagText.map((tag, index) => (
            <Hashtag>
              <CompleteHashtagWrapper>
                <HashtagSharp># </HashtagSharp>
                <CompletedHashtag>{tag}</CompletedHashtag>
              </CompleteHashtagWrapper>
              <DeleteHashtagIcon />
            </Hashtag>
          ))}
);


  <Hashtag>
            <HashtagWrapper>
              <HashtagSharp># </HashtagSharp>
              <HashtagInput
                placeholder="Hashtag"
                onKeyDown={handleEnterHashtag}  //onKeyDown로 함수 설정
                // onChange={checkHashtagText}
                inputWidth={hashtagLength}
              />
            </HashtagWrapper>
          </Hashtag>

Hashtags 동적으로 width값 설정해주기

  1. onChange(HTML 요소의 값이 변경될 때 발생하는 이벤트를 처리하는 핸들러 함수를 지정하는 속성(props))로 입력되는 text 확인
  2. text를 확인하는 함수 checkHashtagText는 input 값이 공백이 아니면, 한국어인지 한국어가 아닌지 살펴본 다음 길이를 설정
  3. style에 반영

[ 전체 코드 ]

  const [hashtagLength, setHashtagLength] = useState<number>(0);

  function checkHashtagText(e: React.ChangeEvent<HTMLInputElement>) {
    const hashtagValue = e.target.value;
    const koreanLength = hashtagValue.length * 1.5 + 1;
    const nonKoreanLength = hashtagValue.length * 1.2 + 1;

    hashtagValue.trim() !== ""
      ? checkKorean(hashtagValue)
        ? setHashtagLength(koreanLength)
        : setHashtagLength(nonKoreanLength)
      : setHashtagLength(0);
  }


return(
 <Hashtag>
            <HashtagWrapper>
              <HashtagSharp># </HashtagSharp>
              <HashtagInput
                placeholder="Hashtag"
                onKeyDown={handleEnterHashtag}
                onChange={checkHashtagText}
                inputWidth={hashtagLength}
              />
            </HashtagWrapper>
          </Hashtag>
)

const HashtagInput = styled.input<{ inputWidth: number }>`
  display: flex;

  width: ${({ inputWidth }) => (inputWidth === 0 ? 9 : inputWidth)}rem;
  ${({ theme }) => theme.fonts.hashtag};

  color: ${({ theme }) => theme.colors.gray1};

  ::placeholder {
    color: ${({ theme }) => theme.colors.gray3};
  }
`;

리팩토링 해야할 부분

  1. 중복 코드 제거 -> 함수 분리
function calculateHashtagLength(hashtagValue: string) {
    const koreanLength = hashtagValue.length * 1.5 + 1;
    const nonKoreanLength = hashtagValue.length * 1.2 + 1;

    return checkKorean(hashtagValue) ? koreanLength : nonKoreanLength;
  }

  function checkHashtagText(e: React.ChangeEvent<HTMLInputElement>) {
    const hashtagValue = e.target.value;
    const hashtagLength = hashtagValue.trim() !== "" ? calculateHashtagLength(hashtagValue) : 0;
    setHashtagLength(hashtagLength);
  }