TIL | React 체크박스(전체 선택, 체크 해제)

ryan·2020년 11월 1일
15

React

목록 보기
19/20
post-thumbnail
post-custom-banner

체크박스 선택, 해제 기능

구현해야할 기능

  1. 전체선택/해제
  2. 전체선택 후, 하나라도 체크가 사라지면 전체 선택 해제
  3. 모든 체크 박스 선택 시, 전체 선택 활성화
// 부모 컴포넌트
import React, { useState, useEffect } from "react";
import OrderManagementArea from "./Component/OrderManagementArea/OrderManagementArea";
import styled from "styled-components";


function Order(props) {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [postsPerPage, setPostsPerPage] = useState(50);

  useEffect(() => {
    const fetchDatas = async () => {
      setLoading(true);
      const res = await axios.get(
        "https://jsonplaceholder.typicode.com/comments"
      );
      setPosts(res.data);
      setLoading(false);
    };

    fetchDatas();
  }, []);


  // Change the number of data by select option
  const handleDataNumber = (e) => {
    // postPerpage의 type이 (select>option.value) string이기 때문에 number로 바꾸어준다.
    // 이 부분에서 TypeScript의 중요성을 알게 되었다.
    setPostsPerPage(Number(e.target.value));
    setCurrentPage(1);
  }; 
}

return(
    <Orderwrap>
     {/* 주문 관리 리스트 영역 */}
      <OrderManagementArea
        data={posts}
        posts={currentPosts}
        loading={loading}
        postsPerPage={postsPerPage}
        totalPosts={posts.length}
        handleSortDate={handleSortDate}
        paginate={paginate}
        handleDataNumber={handleDataNumber}
        />
    </Orderwrap>
)

export default order;

console.log에는 같은 값으로 나오지만, 색깔이 다르다면 type을 의심하자.

// 자식 컴포넌트
import React, { useState, useEffect } from "react";

function OrderManagementArea({
  posts,
  loading,
  postsPerPage,
  totalPosts,
  handleSortDate,
  paginate,
  handleDataNumber,
}) {
  const [checkItems, setCheckItems] = useState([]);

  // 페이지 네이션 부분
  const pageNumbers = [];

  for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) {
    pageNumbers.push(i);
  }

  // 체크박스 전체 단일 개체 선택
  const handleSingleCheck = (checked, id) => {
    if (checked) {
      setCheckItems([...checkItems, id]);
    } else {
      // 체크 해제
      setCheckItems(checkItems.filter((el) => el !== id));
    }
  };

  // 체크박스 전체 선택
  const handleAllCheck = (checked) => {
    if (checked) {
      console.log("wow");
      const idArray = [];
      // 전체 체크 박스가 체크 되면 id를 가진 모든 elements를 배열에 넣어주어서,
      // 전체 체크 박스 체크
      posts.forEach((el) => idArray.push(el.id));
      setCheckItems(idArray);
    }

    // 반대의 경우 전체 체크 박스 체크 삭제
    else {
      setCheckItems([]);
    }
  };

  const handleChange = (e) => {
    handleDataNumber(e);
    setCheckItems([]);
  };

  console.log(checkItems.length);
  console.log(typeof postsPerPage);
  
  return (
  	<OrderManagementSection>
        {/* 검색 정렬 */}
          <div>
            <div>
              <select name="" id="" onChange={handleSortDate}>
                <option value="최신주문일순">최신주문일순</option>
                <option value="주문일의 역순">주문일의 역순</option>
              </select>
            </div>
            <div>
              <select name="" id="" defaultValue="50" onChange={handleChange}>
                <option value="10">10개씩보기</option>
                <option value="20">20개씩보기</option>
                <option value="50">50개씩보기</option>
                <option value="100">100개씩보기</option>
                <option value="150">150개씩보기</option>
              </select>
            </div>
          </div>
      //...
          <th style={{ width: "19px" }}>
            <div>
              <span>
                <TableHeadCheckBox
                  name="checkAll"
                  type={"checkbox"}
                  onChange={(e) => handleAllCheck(e.target.checked)}
                  // checkItems의 갯 수와 불러오는 데이터가 같을 때, 전체 선택을 활성화                           
                  // 하나라도 빼면 체크 박스 해제
                  checked={
                    checkItems.length === postsPerPage
                      ? true
                    : false
                  }
                  />
              </span>
            </div>
          </th>
      //...
        <tbody>
            {posts.map((el, index) => (
              <OrderTableData
                data={el}
                index={index}
                checkItems={checkItems}
                setCheckItems={setCheckItems}
                handleSingleCheck={handleSingleCheck}
                loading={loading}
              />
            ))}
          </tbody>
    </OrderManagementSection>
  )
// 자식의 자식 컴포넌트
import React, { useState, useEffect, Fragment } from "react";
import { useHistory } from "react-router-dom";
import styled from "styled-components";
import { Link } from "react-router-dom";

function OrderTableData({
  data,
  handleSingleCheck,
  checkItems,
  loading,
  index,
  setCheckItems,
}) {
  if (loading) {
    return <h2>Loading...</h2>;
  }

  const history = useHistory();

  return (
    <Fragment>
      <TableRow>
        <td>
          <div>
            <span>
              <TableDataCheckBox
                type={"checkbox"}
                onChange={(e) => handleSingleCheck(e.target.checked, data.id)}
                // checkItems에 data.id가 있으면 체크 아니면 체크 해제
                checked={checkItems.includes(data.id) ? true : false}
              />
            </span>
          </div>
        </td>
        <td>{data.postId}</td>
        <td>{data.id}</td>
        <td>{data.order_number}</td> */}
        <td>
          <Link to="/orderdetail">{data.postIdr}</Link>
        </td>
        <td>{data.name}</td>
        <td>{data.email}</td>
        <td>{data.body}</td>
        <td>{data.quantity}</td>
        <td>{data.orderer_name}</td>
        <td>{data.phone_number}</td>
        <td>{data.payment_amount}</td>
        <td>{data.order_status}</td>
      </TableRow>
    </Fragment>
  );
}

export default OrderTableData;

const TableRow = styled.tr``;
const TableDataCheckBox = styled.input``;

profile
👨🏻‍💻☕️ 🎹🎵 🐰🎶 🛫📷
post-custom-banner

5개의 댓글

comment-user-thumbnail
2020년 11월 2일

이야 코드가 정말 멋지네요

답글 달기
comment-user-thumbnail
2020년 11월 8일

와... 상준님 브랜디가시고 진짜 실력 폭발하신거 같아요! 저 나중에 이거 좀 알려주세요.. 체크박스 극혐...

답글 달기
comment-user-thumbnail
2020년 11월 8일

와... 상준님 브랜디가시고 진짜 실력 폭발하신거 같아요! 저 나중에 이거 좀 알려주세요.. 체크박스 극혐...

답글 달기
comment-user-thumbnail
2021년 7월 21일

감이 안 잡혔는데 참고해서 코드 완성했습니다 감사합니다 ㅠㅠ

답글 달기
comment-user-thumbnail
2022년 10월 26일

멋진 코드 감사합니다‼️!

답글 달기