[React] 벨로그처럼 태그 기능 만들기

SEUNGJUN JEONG·2023년 9월 4일
1

WEB Front-End

목록 보기
10/10
post-thumbnail

벨로그 따라잡기 프로젝트의 일환으로 벨로그에서 사용하는 태그 방식을 따라서 만들어봤습니다. React와 TypeScript를 기반으로 합니다. 스타일링은 Tailwind CSS로 했습니다.

작동 방식


벨로그 태그 기능의 작동 방식을 보면 태그를 담는 div 안에 태그가 하나씩 div로 들어갑니다.
태그를 담는 useState([]) 형식의 배열이 있다고 할 때, 여기에 태그를 담고 JSX 코드에서는 이 배열을 map() 으로 렌더링하는 것이죠.
따라서 전체적인 원리는 To-do List와 비슷하다고 할 수 있겠습니다.

전체 코드

import React from "react";
import { useState } from "react";


const Keyword = () => {
  /* keyword */
  const [tags, setTags] = useState<string[]>([]);
  const [tag, setTag] = useState<string>("");

  const removeTag = (i: number) => {
    const clonetags = tags.slice();
    clonetags.splice(i, 1);
    setTags(clonetags);
  };

  const tagInputListener = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 태그 입력 관리
    setTag(e.target.value);
  };

  const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      handleEnter();
    }
  };

  const handleEnter = () => {
    if (tags.includes(tag)) {
      setTag("");
      return;
    }
    if (tag === "") return;
    const updatedTags = [...tags, tag];
    setTags(updatedTags);
    setTag("");
  };


  return (
    <div className="w-[350px] h-auto flex flex-col items-center justify-center overflow-auto">
      {tags.length !== 0 && (
        <div className="pl-[12px] flex flex-wrap items-center w-[350px] mb-[10px] break-all">
          {tags.map((e, i) => (
            <div
              key={i}
              className="cursor-pointer flex justify-center items-center bg-light-blue rounded-3xl p-4 mt-[10px] mr-[10px] mb-[10px] h-[40px]"
              onClick={() => removeTag(i)}
            >
              <p className="font-main text-black text-[14px]">{e}</p>
            </div>
          ))}
        </div>
      )}
      <input type="text" className="hidden" />
      <input
        className="w-[320px] mt-[5px] text-[15px] outline-none border-b border-gray-300"
        type="text"
        placeholder="키워드를 입력하세요"
        value={tag}
        onChange={(e) => tagInputListener(e)}
        onKeyPress={(e) => handleKeyPress(e)}
      />
    </div>
  );
};

export default Keyword;

태그 관리

const [tags, setTags] = useState<string[]>([]); // 태그들
const [tag, setTag] = useState<string>(""); // 지금 적을 태그

태그들을 담을 배열과 지금 적을 태그의 상태를 담는 string 변수를 새롭게 정의합니다.

const removeTag = (i: number) => {
    const clonetags = tags.slice();
    clonetags.splice(i, 1);
    setTags(clonetags);
};

태그를 삭제하는 함수입니다.
slice() 로 태그들을 복사하고 splice() 로 태그들 중 사용자가 삭제한 태그를 삭제합니다.
마지막으로 tags 배열을 최신 상태로 업데이트 합니다.

const tagInputListener = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 태그 입력 관리
    setTag(e.target.value);
};

태그 입력을 관리하는 함수입니다. 태그를 입력하는 칸의 onChange() 에 할당되어 입력할 때 마다 실행되어 입력 중인 태그를 관리합니다.

const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      handleEnter();
    }
};

const handleEnter = () => {
    if (tags.includes(tag)) {
      setTag("");
      return;
    }
    if (tag === "") return;
    const updatedTags = [...tags, tag];
    setTags(updatedTags);
    setTag("");
};

이 실습에서 태그 입력을 마친다는 뜻은 Enter 키를 입력하는 것으로 하겠습니다.
Enter 를 누르면 먼저 지금 입력한 태그가 중복되지는 않았는지 검사한 후 조건을 만족한다면 태그 배열을 새롭게 업데이트하고 태그 입력칸은 다시 빈칸으로 만듭니다.

profile
Microsoft Learn Student Ambassadors

0개의 댓글