체크박스 기능 구현하기(2)

D9·2022년 7월 26일
0

React Checkbox

목록 보기
2/2

앞서 진행했던 체크박스기능 구현에서, 컴포넌트를 재활용하여 코드를 좀 더 보기좋게 만들어 보도록 하겠습니다.

import React, { useState, useMemo } from "react";
import styled from "styled-components";

function App() {
  const [checkedList, setCheckedList] = useState([]);
  
  const isCheckedAll = useMemo(
    () => checkedList.length === 5,
    [checkedList.length]
  );

  const changeHandler = ({ target }) => {
    checkedList.includes(target.name)
      ? setCheckedList((prev) => prev.filter((item) => item !== target.name))
      : setCheckedList((prev) => [...prev, target.name]);
  };

  const changeAllHandler = () => {
    isCheckedAll === true
      ? setCheckedList([])
      : setCheckedList(["checkA", "checkB", "checkC", "checkD", "checkE"]);
  };

  return (
    <Main>
      <CheckBoxAll
        type="checkbox"
        name="CheckAll"
        onChange={changeAllHandler}
        checked={isCheckedAll}
      />

      <Content>
        <CheckBoxA
          type="checkbox"
          name="checkA"
          onChange={changeHandler}
          checked={checkedList.includes("checkA")}
        />
        <CheckBoxB
          type="checkbox"
          name="checkB"
          onChange={changeHandler}
          checked={checkedList.includes("checkB")}
        />
        <CheckBoxC
          type="checkbox"
          name="checkC"
          onChange={changeHandler}
          checked={checkedList.includes("checkC")}
        />
        <CheckBoxD
          type="checkbox"
          name="checkD"
          onChange={changeHandler}
          checked={checkedList.includes("checkD")}
        />
        <CheckBoxE
          type="checkbox"
          name="checkE"
          onChange={changeHandler}
          checked={checkedList.includes("checkE")}
        />
      </Content>
    </Main>
  );
}

export default App;

const Main = styled.div`
  width: 100%;
  height: 100%;
  background-color: aliceblue;
`;

const CheckBoxAll = styled.input`
  width: 100%;
`;

const Content = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background-color: antiquewhite;
`;

const CheckBoxA = styled(CheckBoxAll)``;
const CheckBoxB = styled(CheckBoxAll)``;
const CheckBoxC = styled(CheckBoxAll)``;
const CheckBoxD = styled(CheckBoxAll)``;
const CheckBoxE = styled(CheckBoxAll)``;

여기에서 전체선택을 제외한 각각의 체크박스는 스타일과 기능이 동일하다고 봤을때, 하나의 컴포넌트를 만들어서 통합 관리해 줄 수 있습니다.

체크박스 컴포넌트 만들어주기

하나의 체크박스 컴포넌트를 만들어 보겠습니다.

새로운 Checkbox.js 라는 파일을 만들어 줍니다.

import React from "react";
import styled from "styled-components";

const CheckBox = () => {
  return ();
};

export default CheckBox;

여기서 check라는 새로운 체크박스 인풋을 만들어 주도록 하겠습니다.

const CheckBox = ({ checkedList, setCheckedList, children }) => {
  return (
    <Check
      type="checkbox"
    />
  );
};

export default CheckBox;

const Check = styled.input`
  width: 100%;
`;

이제 부모 컴포넌트에서 필요한 요소들을 prop으로 전달받도록 하겠습니다.

필요한 요소들을 생각해봤을때 체크여부를 확인하기 위한 checkedList 와 체크를 눌렀을때 checkedList state에 값을 넣어줄 setCheckedList, 그리고 checkbox의 name을 대신할 children을 prop으로 받아옵니다.

부모컴포넌트(App.js)

import React, { useState, useMemo } from "react";
import styled from "styled-components";
import CheckBox from "./component/CheckBox"; //만들어둔 checkbox 컴포넌트를 import 해오기

function App() {
  const [checkedList, setCheckedList] = useState([]);

  const isCheckedAll = useMemo(
    () => checkedList.length === 5,
    [checkedList.length]
  );

  const changeAllHandler = () => {
    isCheckedAll
      ? setCheckedList([])
      : setCheckedList([
          "checkOne",
          "checkTwo",
          "checkThree",
          "checkFour",
          "checkFive",
        ]);
  };

  return (
    <Main>
      <CheckBoxAll
        type="checkbox"
        name="CheckAll"
        onChange={changeAllHandler}
        checked={isCheckedAll}
      />

      <Content>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkOne
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkTwo
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkThree
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkFour
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkFive
        </CheckBox>
      </Content>
    </Main>
  );
}

export default App;

const Main = styled.div`
  width: 100%;
  height: 100%;
  background-color: aliceblue;
`;

const CheckBoxAll = styled.input`
  width: 100%;
`;

const Content = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background-color: antiquewhite;
`;

자식컴포넌트 (Checkbox.js)

import React from "react";
import styled from "styled-components";

const CheckBox = ({ checkedList, setCheckedList, children }) => {

  return (
    <Check
      type="checkbox"
      checked={checkedList.includes(children)}
    />
  );
};

export default CheckBox;

const Check = styled.input`
  width: 100%;
`;

이제 체크박스를 눌렀을때 작동할 함수 changeHandler를 만들어주겠습니다.

일단 onChange에 콜백함수로 changeHandler를 호출하는데, 이때 체크박스를 눌렀을때

checkedList 배열에 children 요소를 추가해줄 예정이니, children을 인수로 보내줍니다.

    <Check
      type="checkbox"
      onChange={() => changeHandler(children)}
      checked={checkedList.includes(children)}
    />

그리고 changeHandler 함수는 children 이라는 인수를 name이라는 매개변수로 받아 checkedList에 추가 또는 제거 해주면 되기 때문에

const changeHandler = (name) => {
    checkedList.includes(name)
      ? setCheckedList((prev) => prev.filter((item) => item !== name))
      : setCheckedList((prev) => [...prev, name]);
  };

이렇게 해주면, 모든 체크박스의 상태관리를 각각의 체크박스가 아닌 부모컴포넌트에서 통합관리하고,

각각의 체크박스에서 함수를 통해 부모컴포넌트의 state값에 접근하도록 해주면 됩니다.

따라서

최종코드

App.js

import React, { useState, useMemo } from "react";
import styled from "styled-components";
import CheckBox from "./component/CheckBox";

function App() {
  const [checkedList, setCheckedList] = useState([]);

  const isCheckedAll = useMemo(
    () => checkedList.length === 5,
    [checkedList.length]
  );

  const changeAllHandler = () => {
    isCheckedAll
      ? setCheckedList([])
      : setCheckedList([
          "checkOne",
          "checkTwo",
          "checkThree",
          "checkFour",
          "checkFive",
        ]);
  };

  return (
    <Main>
      <CheckBoxAll
        type="checkbox"
        name="CheckAll"
        onChange={changeAllHandler}
        checked={isCheckedAll}
      />

      <Content>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkOne
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkTwo
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkThree
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkFour
        </CheckBox>
        <CheckBox checkedList={checkedList} setCheckedList={setCheckedList}>
          checkFive
        </CheckBox>
      </Content>
    </Main>
  );
}

export default App;

const Main = styled.div`
  width: 100%;
  height: 100%;
  background-color: aliceblue;
`;

const CheckBoxAll = styled.input`
  width: 100%;
`;

const Content = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background-color: antiquewhite;
`;

Checkbox.js

import React from "react";
import styled from "styled-components";

const CheckBox = ({ checkedList, setCheckedList, children }) => {
  const changeHandler = (name) => {
    checkedList.includes(name)
      ? setCheckedList((prev) => prev.filter((item) => item !== name))
      : setCheckedList((prev) => [...prev, name]);
  };

  return (
    <Check
      type="checkbox"
      onChange={() => changeHandler(children)}
      checked={checkedList.includes(children)}
    />
  );
};

export default CheckBox;

const Check = styled.input`
  width: 100%;
`;

이렇게 Checkbox라는 컴포넌트를 만들어서 재활용 해 줄 수 있습니다.

아직 부족한 부분이 많습니다.

혹시나 틀린부분이나 수정할 부분이 있다면 댓글로 알려주시면 감사하겠습니다.

profile
새로운 시작

0개의 댓글