체크된 아이템들 저장할 배열을 관리할 useState 생성
const [checkedItem, setCheckedItem] = useState([]);
const handleCheck = (e, item) => {
const isChecked = e.target.checked;
if (isChecked) setCheckedItem((prev) => [...prev, item.id]);
else setCheckedItem((prev) => prev.filter((id) => id !== item.id));
};
해당 checkbox가 checked되면 setCheckedItem배열에 해당 id를 저장
checked되지 않으면 해당 id와 일치하지 않은 id들을 setCheckedItem에 저장
{paginatedList.map((data) => (
<tr
key={data.id}
className={checkedItem.includes(data.id) ? "checked" : ""}
>
<td>
<input
type="checkbox"
onChange={(e) => handleCheck(e, data)}
checked={checkedItem.includes(data.id) ? true : false}
/>
</td>
<td>{data.id}</td>
<td>{data.title}</td>
<td>{data.date}</td>
</tr>
))}
checked={checkedItem.includes(data.id) ? true : false}
className={checkedItem.includes(data.id) ? "checked" : ""}
const handleCheckAll = (e) => {
const isChecked = e.target.checked;
if (isChecked) {
const allItemIds = paginatedList.map((item) => item.id);
setCheckedItem(allItemIds);
} else setCheckedItem([]);
};
전체선택 checkbox가 checked되면 allItemIds에 보여지는 페이지의 item들의 id를 저장하여 setCheckedItem에 allItemIds를 저장
checked되지 않으면 setCheckedItem 빈배열
<input
type="checkbox"
onChange={(e) => handleCheckAll(e)}
checked={checkedItem.length === paginatedList.length}
/>
checkedItem 길이와 현 페이지의 아이템들의 길이가 같을 때 checked되도록 지정 => 길이가 같지 않을 경우 전체선택 checkbox 해제
const handleCheck = (e, item) => {
const isChecked = e.target.checked;
setCheckedItem((prev) => (
isChecked ? [...prev, item.id] : prev.filter((id) => id !== item.id)
));
};
const handleCheckAll = (e) => {
const isChecked = e.target.checked;
setCheckedItem(isChecked ? paginatedList.map((item) => item.id) : []);
};
import { useState, useEffect } from "react";
import data from "../src/utils/db.json";
import "./App.css";
function App() {
//pagination
const [selected, setSelected] = useState(5); // 한 페이지에 보여질 게시물 수
const [page, setPage] = useState(1); // 현재 페이지
//checkbox
const [checkedItem, setCheckedItem] = useState([]);
//pagination
const startIdx = (page - 1) * selected; // 한 페이지의 첫 게시물 인덱스
const endIdx = startIdx + selected; // 한 페이지의 마지막 게시물 인덱스
const paginatedList = data.slice(startIdx, endIdx); // 한 페이지의 게시물들
const pagingCount = Math.ceil(data.length / selected); // 총 페이지 갯수
const pageIdx = []; // 총 페이지들
for (let i = 1; i <= pagingCount; i++) {
pageIdx.push(i);
}
const handlePageChange = (page) => {
!isNaN(page) && page >= 1 && page <= pagingCount
? setPage(page)
: alert("페이지의 끝입니다.");
setCheckedItem([]); //페이지가 넘어가면 체크 리셋
};
const handleSelect = (e) => {
setSelected(Number(e.target.value));
setPage(1);
};
//checkbox
const handleCheck = (e, item) => {
const isChecked = e.target.checked;
setCheckedItem((prev) =>
isChecked ? [...prev, item.id] : prev.filter((id) => id !== item.id)
);
};
const handleCheckAll = (e) => {
const isChecked = e.target.checked;
setCheckedItem(isChecked ? paginatedList.map((item) => item.id) : []);
};
return (
<div className="App">
<select onChange={handleSelect} value={selected}>
{[5, 6, 7, 8, 9, 10].map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
<table>
<thead>
<tr>
<td>
<input
type="checkbox"
onChange={(e) => handleCheckAll(e)}
checked={checkedItem.length === paginatedList.length}
/>
</td>
<th>No</th>
<th>Title</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{paginatedList.map((data) => (
<tr
key={data.id}
className={checkedItem.includes(data.id) ? "checked" : ""}
>
<td>
<input
type="checkbox"
onChange={(e) => handleCheck(e, data)}
checked={checkedItem.includes(data.id) ? true : false}
/>
</td>
<td>{data.id}</td>
<td>{data.title}</td>
<td>{data.date}</td>
</tr>
))}
</tbody>
</table>
<ul>
<li onClick={() => handlePageChange(1)}>⏪️</li>
<li onClick={() => handlePageChange(page - 1)}>◀️</li>
{pageIdx.map((i) => (
<li
key={i}
onClick={() => handlePageChange(i)}
className={page === i && "active"}
>
{i}
</li>
))}
<li onClick={() => handlePageChange(page + 1)}>▶️</li>
<li onClick={() => handlePageChange(pagingCount)}>⏩️</li>
</ul>
</div>
);
}
export default App;
❖참고사항
console로 checkItem 출력하면 선택한 아이템이 제대로 들어가지 않는 것을 볼 수 있었다.
하지만 useState함수는 비동기적으로 동작할 수 있기 때문에 console.log(checkedItem)는 즉시 실행되지만 setCheckedItem함수가 상태를 업데이트하고 그 값이 반영되는데는 시간이 걸릴 수 있기 때문이다.
즉시 업데이트 되는 것을 확인하고 싶다면 useEffect를 사용하면 가능하다.
useEffect(() => {
console.log(checkedItem);
}, [checkedItem]);