본문 바로가기
개발일지/트친소 생성기 사이트

[원신 X친소표 사이트 제작기] 5. 다중 체크 리스트픽 만들기 #React

by 박기린 2024. 12. 9.

 

 


다중 Check List 메뉴

미리 체크리스트를 주고, 원하는 만큼 골라서 추가할 수 있는 리스트픽 컴포넌트가 필요합니다.

트위터 활동은 동시에 다양하게 할 수 있기 때문에, 하나를 체크했다고 다른 체크가 풀리는 게 아니라, 다중으로 체크가 되어야 합니다.

 

 

지금부터 다중 체크리스트 컴포넌트를 제작하겠습니다.

 

 


CheckList 컴포넌트

          <Checklist
            placeholder="트위터 활동"
            elements={["RT", "마음", "일상/글", "그림", "구독"]}
            onChecked={(e) => setXType(e)}
          />

CheckList 컴포넌트를 페이지로 호출하면, 위와 같은 DOM이 출력됩니다.

 

 

 

CheckList 소스코드

import { FormTextContainer, FormText, ChecklistText } from "@/styles/Texts";
import {
  CheckboxInput,
  CheckboxLabel,
  ChecklistSpacer,
} from "@/styles/CheckBox";
import { ChecklistContainer } from "@/styles/Containers";
import React, { useState } from "react";


export default function Checklist(props) {
  const { elements = [1, 2, 3], onChecked, placeholder } = props;
  const [checkedList, setCheckedList] = useState(
    new Array(elements.length).fill(false)
  );

  const handleChange = (e, idx) => {
    const { checked } = e.target;
    const newCheckedList = [...checkedList];
    newCheckedList[idx] = checked;
    setCheckedList(newCheckedList);
    let newStr = "";

    elements.forEach((e, idx) => {
      if (newCheckedList[idx] === true) {
        newStr += e + " | ";
      }
    });

    onChecked(newStr.slice(0, -3));
  };

  return (
    <ChecklistContainer>
      <FormTextContainer>
        <FormText>{placeholder}</FormText>
      </FormTextContainer>
      <ChecklistSpacer />
      {elements.map((element, idx) => (
        <CheckboxLabel key={idx}>
          <CheckboxInput
            type="checkbox"
            checked={checkedList[idx]}
            onChange={(e) => handleChange(e, idx)}
          />
          <ChecklistText>{element}</ChecklistText>
        </CheckboxLabel>
      ))}
    </ChecklistContainer>
  );
}

 

 

props 설정

  const { elements, onChecked, placeholder } = props;

부모 컴포넌트로부터 3가지 props를 전달받습니다.


elements : 체크리스트 항목으로 구성된 배열입니다.
onChecked : 선택된 체크박스 정보가 담긴 state를 상위 컴포넌트에 전달하는 콜백 함수입니다.
placeholder : 체크리스트 상단에 나타나는 설명 텍스트입니다.

 

 

 

State 설정

  const [checkedList, setCheckedList] = useState(
    new Array(elements.length).fill(false)
  );

checkedList State는 각 항목의 선택 여부를 추적하는 Array입니다.
초기값은 new Array(elements.length).fill(false)로, 모든 체크박스가 선택되지 않은 상태로 시작합니다.

 

 

 

핸들러 함수 :  handleChange

  const handleChange = (e, idx) => {
    const { checked } = e.target;
    const newCheckedList = [...checkedList];
    newCheckedList[idx] = checked;
    setCheckedList(newCheckedList);
    let newStr = "";

    elements.forEach((e, idx) => {
      if (newCheckedList[idx] === true) {
        newStr += e + " | ";
      }
    });

    onChecked(newStr.slice(0, -3));
  };

 

체크박스를 클릭할 때 호출되는 콜백함수입니다.


1. e.target.checked로 현재 체크박스의 boolean 상태를 확인합니다. (체크되면 true, 해제되면 false)
2. 기존 checkedList를 깊은 복사(newCheckedList)한 후, 체크/체크해제된 값만 변경하고, setCheckedList로 상태를 업데이트합니다.
3. 체크리스트 정보가 담긴 elements를 forEach()문으로 순회합니다.

     만약 해당 순서의 newCheckedList값이 true일 경우, newStr이라는 String 변수에 해당 element(e)를 추가합니다.
     선택된 항목은 " | "로 구분되며 마지막 구분자는 slice(0, -3)을 이용해서 제거됩니다.
4. 조합된 문자열인 newStr을 onChecked 함수에 전달해서, 상위 컴포넌트에 전달합니다.

 

 

 

JSX 분석

    <ChecklistContainer>
      <FormTextContainer>
        <FormText>{placeholder}</FormText>
      </FormTextContainer>
      <ChecklistSpacer />
      {elements.map((element, idx) => (
        <CheckboxLabel key={idx}>
          <CheckboxInput
            type="checkbox"
            checked={checkedList[idx]}
            onChange={(e) => handleChange(e, idx)}
          />
          <ChecklistText>{element}</ChecklistText>
        </CheckboxLabel>
      ))}
    </ChecklistContainer>


ChecklistContainer : 전체 컴포넌트를 감싸는 컨테이너입니다.
FormTextContainerFormText : 설명 텍스트(placeholder)를 표시합니다.
ChecklistSpacer : 텍스트(FormText)와 체크리스트 사이의 간격을 만듭니다.

 

체크박스 리스트 : elements 배열을 map으로 순회하여 각각의 체크박스와 레이블을 생성합니다.
  CheckboxInput : 체크박스를 표시하며, 체크 여부도 확인할 수 있습니다.
  ChecklistText : 해당 체크박스가 어떤 내용인지를 설명하는 텍스트입니다.

 

 

 

 

Styled-Components

ChecklistContainer, FormText, FormTextContainer, ChecklistSpacer, CheckboxInput, ChecklistText 모두 특별한 기능이 추가된 컴포넌트가 아니라, styled-components로 스타일만 입힌 컴포넌트입니다.

스타일 컴포넌트의 코드 전문을 보고 싶으면, 접은 글을 펼치세요.

더보기
const ChecklistContainer = styled.div`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 300px;
  margin-left: 2em;
  margin-top: 1em;
  margin-bottom: 2em;
  /* background-color: pink; */
`;

const FormTextContainer = styled.div`
  display: flex;
  flex: 1;
  justify-content: center;
`;

const FormText = styled.text`
  font-size: 19px;
  font-weight: bold;
`;

const ChecklistSpacer = styled.div`
  height: 10px;
`;

const CheckboxLabel = styled.label`
  display: flex;
  align-items: center;
  margin-bottom: 6px;
  cursor: pointer;
  /* background-color: blue; */
`;

const CheckboxInput = styled.input`
  display: flex;
  justify-content: center;
  align-items: center;
  appearance: none; // 기본 체크박스 스타일 제거
  margin-left: 0px; // 기본으로 설정된 마진 제거
  margin-right: 10px;
  width: 20px;
  height: 20px;
  cursor: pointer;
  background-color: #efecec;
  border-radius: 2px;
  border: none; // 테두리 색도 파란색으로

  // 체크박스가 선택되었을 때의 스타일
  &:checked {
    background-color: blue; // 배경색을 파란색으로
    /* border: 2px solid blue; // 테두리 색도 파란색으로 */
  }

  &:checked:after {
    content: "✔"; // 체크 표시를 추가
    color: white;
    display: block;
    text-align: center;
    font-size: 18px;
  }
`;

 

 

 


작동 구조

원하는 걸 선택한 만큼, X친소 표에 모든 내용이 담깁니다.

 

 

반응형