체크박스 기능 구현해보기(1)

D9·2022년 7월 25일
0

React Checkbox

목록 보기
1/2

체크박스 기능 구현해보기

웹 페이지를 만들다 보면 체크박스 기능을 구현하는 경우가 생기게 됩니다.

나 또한 프로젝트를 진행하면서 체크박스 때문에 애먹었었는데 당시 구현했던 방식을

예를 들에 보겠습니다.

1. 리엑트내에서 체크박스 만들어 보기

일단 여러가지 방식이 많겠지만, React와 StyledComponent를 활용하여 진행하였습니다.

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

function App() {
  return (
    <Main>
      <CheckBoxAll
        type="checkbox"
        name="CheckAll"
      />

      <Content>
        <CheckBoxA
          type="checkbox"
          name="checkA"
        />
        <CheckBoxB
          type="checkbox"
          name="checkB"
        />
        <CheckBoxC
          type="checkbox"
          name="checkC"
        />
        <CheckBoxD
          type="checkbox"
          name="checkD"
        />
        <CheckBoxE
          type="checkbox"
          name="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)``;

일단 전체선택을 관리하는 CheckBoxAll 과 각각의 checkbox를 생성해 주었습니다.

(각각의 checkbox는 임의로 name attribute를 A,B,C,D,E 로 설정하였습니다.)

체크박스는 생성되었지만, 아직은 전체선택과 각각의 체크박스가 유동적으로 작동하지는 않습니다.

일단 생각해야할 부분은 전체선택을 선택, 해제 할 때 나머지 박스들이 동일하게 선택, 해제가 되어야하고,

나머지 박스들이 모두 선택되었을 때 전체선택 부분이 자동으로 체크가 되고, 하나라도 해제되었을 때에는 전체선택부분이 해제되어야 합니다.

이 부분에서 저는 일단 배열로서 접근을 하여, 선택된 체크들의 상태리스트 배열을 만들어주고, 체크가 되었을때, 체크된 박스들이 배열에 포함되도록 하였습니다.

2. 체크된 박스들의 배열상태 추가해주기

체크가 될때마다 체크된 박스들이 배열에 추가되어야 하기때문에 체크된 박스의 배열을 하나 만들어주고 각각의 박스에 onChange 함수를 통해서 배열에 추가 또는 제거를 해주어야 합니다.

일단 체크된 박스들의 상태를 관리해줄 checkedList 라는 state 값을 만들어준다.

const [checkedList, setCheckedList] = useState([]);

처음에는 체크된것들이 없는 경우에는 빈배열로, 체크된상태로 시작하려면 배열안에 특정 값을 모두 넣어주면 된다.(여기서 나는 name attribute를 통해 관리하기때문에 체크된상태로 시작하려면

[checkedA, checkedB, checkedC, checkedD, checkedE]

로 두면 되는데, 이건 관리하는 상태값에따라 조정해주면 됩니다.)

스테이트값을 만들어 주었다면, 각각의 체크박스에 onChange 함수를 만들어주어, 체크되었을때 배열에 값을 넣어주면 됩니다.

  const changeHandler = ({ target }) => {
    checkedList.includes(target.name)
      ? setCheckedList((prev) => prev.filter((item) => item !== target.name))
      : setCheckedList((prev) => [...prev, target.name]);
  };
//체크박스를 눌렀을때 setCheckedList를 통해 배열에 name값을 넣어주거나, filter 함수를 통해
제거해주게 합니다.

삼항연산자를 통해 배열에 이름이 있는경우에는 제거, 없을때는 추가 해주는 함수를 추가해줍니다.

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

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

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

  return (
    <Main>
      <CheckBoxAll
        type="checkbox"
        name="CheckAll"
      />

      <Content>
        <CheckBoxA
          type="checkbox"
          name="checkA"
          onChange={changeHandler}
        />
        <CheckBoxB
          type="checkbox"
          name="checkB"
          onChange={changeHandler}
        />
        <CheckBoxC
          type="checkbox"
          name="checkC"
          onChange={changeHandler}
        />
        <CheckBoxD
          type="checkbox"
          name="checkD"
          onChange={changeHandler}
        />
        <CheckBoxE
          type="checkbox"
          name="checkE"
          onChange={changeHandler}
        />
      </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)``;

3. 전체선택 체크박스 관리

전체선택을 눌렀을때 마찬가지로 나머지 다섯개의 박스들이 선택이 되어야하고, 전체선택을 해제했을때 나머지 박스들이 해제되어야 하기 때문에

전체선택 체크박스에대한 변수를 지정해주는데 state로 관리하기보다 useMemo를 활용해서 전체선택 변수를 지정해 주도록 합니다.

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

checkedList.length가 변할때마다 배열의 길이를 확인하여 isCheckedAll의 값을 true 또는 false 로 관리합니다.

그리고 changeAllHandler 함수를 만들어 전체선택을 눌렀을때 함수가 작동하도록 해줍니다.

  const changeAllHandler = () => {
    isCheckedAll === true
      ? setCheckedList([])
      : setCheckedList(["checkA", "checkB", "checkC", "checkD", "checkE"]);
  };
  // 전체선택을 체크했을 때 true, false를 통해 배열에 나머지 모든 체크의 속성을 넣어주거나, 
  해제했을때에는 빈배열로 만듭니다.

굳이 state로 관리하여 쓸데없는 랜더링을 만들기 보다는 useMemo를 활용하여 변수로 관리하게 되면 좀 더 효율적으로 관리할 수 있습니다.

이렇게만 해준다면, 콘솔에 에러가 뜨는걸 볼 수 있습니다.

체크박스가 체크되고, 되지 않는 상태를 관리를 따로 해줘야 한다.. 뭐 이런오류가 뜨게 되기때문에

각각의 체크박스에 checked 속성을 지정해 주어야 합니다.

checkboxAll 은 checkedAll 이 true,false냐에 따라 checked값이 결정되고,

나머지 박스들은 checkedList에 각각의 name 들이 들어있는지를 통해 checked 값이 결정되기 때문에 이것을 추가해주면,

최종코드

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)``;

간략하게 적어보았습니다.

더 좋은 방법과 지금 제가 적은 부분에서도 고칠점이 많지만

댓글로 알려주시면 감사하겠습니다!

profile
새로운 시작

0개의 댓글