탭 메뉴 만들기

Donggu(oo)·2023년 1월 22일
0

React 기능 구현

목록 보기
6/14
post-thumbnail

1. 알아야 할 내용


  • 아래의 () => selectMenuHandler(index) 부분에서 selectMenuHandler 함수를 전달할 때 index를 인자로 받고 있다. selectMenuHandler(index)로 전달하게 되면 JSX 문법에 따라 함수의 형태로 이벤트 핸들러를 전달해야 되는 규칙에 어긋나 undefined를 전달하는 것과 같게 되어 Error가 발생한다. 따라서 화살표 함수로 감싸서 함수의 형태로 전달해주어야 한다.
<li className={currentTab === index ? 'submenu focused' : 'submenu'}
  key={index}
  onClick={() => selectMenuHandler(index)}>
  {tab.name}
</li>

2. 전체 코드


  • 탭 메뉴 구현 코드
export const Tab = () => {
  // Tab Menu 중 현재 어떤 Tab이 선택되어 있는지 확인하기 위한 currentTab 상태와 currentTab을 갱신하는 함수
  const [currentTab, setCurrentTab] = useState(0);  // 초기값은 index 0

  const menuArr = [
    { name: 'Tab1', content: 'Tab menu ONE' },
    { name: 'Tab2', content: 'Tab menu TWO' },
    { name: 'Tab3', content: 'Tab menu THREE' },
  ];

  const selectMenuHandler = (index) => {
    // parameter로 현재 선택한 인덱스 값을 전달해야 하며, 이벤트 객체(event)는 쓰지 않아도 자동 전달됨
    // 함수가 실행되면 현재 선택된 Tab Menu 가 갱신된다.
    setCurrentTab(index);
  };

  return (
    <>
      <div>
        <TabMenu>
          {/* li 엘리먼트의 class명의 경우 선택된 tab 은 'submenu focused' 가 되며,  나머지 2개의 tab은 'submenu' 가 된다. */}
          {menuArr.map((tab, index) =>
            <li className={currentTab === index ? 'submenu focused' : 'submenu'}
              key={index}
              onClick={() => selectMenuHandler(index)}>
              {tab.name}
            </li>
          )}

        </TabMenu>
        <Desc>
          {/* 현재 선택된 탭의 content를 표시한다. */}
          <p>{menuArr[currentTab].content}</p>
        </Desc>
      </div>
    </>
  );
};
  • CSS
const TabMenu = styled.ul`
  background-color: #dcdcdc;
  color: rgba(73, 73, 73, 0.5);
  font-weight: bold;
  display: flex;
  flex-direction: row;
  justify-items: center;
  align-items: center;
  list-style: none;
  margin-bottom: 7rem;

  .submenu {
    // 기본 Tabmenu에 대한 CSS
    width: 100%;
    padding: 15px 10px;
    cursor: pointer;
  }

  .focused {
    // 선택된 Tabmenu에만 적용되는 CSS
    background-color: #4000c7;
    color: rgba(255, 255, 255, 1);
    transition: 0.3s;
  }
`;

const Desc = styled.div`
  text-align: center;
`;

3. 실전 예제


  • 기존에는 모든 데이터를 map으로 불러오고 있었지만 탭 기능을 이용하여 전체 리스트, 체크된 리스트, 체크 안된 리스트 3개의 탭으로 보여주는 기능 구현이다.

  • 체크된 리스트를 보여주기 위해 map으로 불러오기 전에 filter로 todoData.filter((value) => checkedItems.includes(value.id)) 체크된 id를 포함하고 있는 리스트만 가져오도록 조건을 주었다.

  • 체크가 안된 리스트는 todoData.filter((value) => !checkedItems.includes(value.id)) 반대의 조건을 주었다.

{currentTab === 0 ?
    <ul className="todoList">
        {todoData.slice(offset, offset + limit).map((value) =>
            <TodoList
                list={value}
                key={value.id}
                deleteButton={deleteTodoText}
                handleCheckChange={handleCheckChange}
                checkedItems={checkedItems}
                todoData={todoData}
                setTodoData={setTodoData}
            />)}
    </ul>
    : (currentTab === 1 ?
        <ul className="todoList">
            {todoData.filter((value) => checkedItems.includes(value.id)).slice(offset, offset + limit).map((value) =>
                <TodoList
                    list={value}
                    key={value.id}
                    deleteButton={deleteTodoText}
                    handleCheckChange={handleCheckChange}
                    checkedItems={checkedItems}
                    todoData={todoData}
                    setTodoData={setTodoData}
                />)}
        </ul>
        : <ul className="todoList">
            {todoData.filter((value) => !checkedItems.includes(value.id)).slice(offset, offset + limit).map((value) =>
                <TodoList
                    list={value}
                    key={value.id}
                    deleteButton={deleteTodoText}
                    handleCheckChange={handleCheckChange}
                    checkedItems={checkedItems}
                    todoData={todoData}
                    setTodoData={setTodoData}
                />)}
        </ul>
    )}

0개의 댓글