부모 컴포넌트의 체크박스의 종류는 총 3가지가 있다.
체크됨
: 모든 항목을 체크함-
: 체크한 항목이 한 개라도 있을 경우. 이 표시를 한 번 클릭했을 때, 체크한 항목이 모두 체크 해제 되어야 함.체크되지 않음
: 체크한 항목이 아예 없을 경우
const [isCheckAll, setIsCheckAll] = useState(false)
const [isCheckingBox, setIsCheckingBox] = useState(false)
const [checkedArr, setCheckedArr] = useState([])
isCheckAll
: 모든 항목을 체크했을 경우의 stateisCheckingBox
: 체크한 항목이 한 개라도 있을 경우의 statecheckedArr
: 체크한 항목의 정보를 객체로 저장시켜주는 stateconst changeAllCheck = (e) => {
if (e.target.checked) {
setIsCheckAll(true)
} else {
setIsCheckAll(false)
setCheckedArr([])
}
}
const checkingCheckedBox = () => {
setIsCheckAll(false)
setIsCheckingBox(true)
setCheckedArr([])
}
<div className='class_check_box'>
<input type='checkbox' id='all_class_checkbox' onClick={e=> changeAllCheck(e)} checked={isCheckAll} />
<label htmlFor='all_class_checkbox' />
{checkedArr.length > 0 && checkedArr.length !== classData.length && (
<img src={checkingCheckbox} onClick={checkingCheckedBox} alt='checkingCheckbox' />
)}
</div>
isCheckAll
state로 관리한다changeAllCheck
온클릭 이벤트가 활성화된다. 체크 여부에 따라 isCheckAll 속성도 바뀐다.setCheckedArr([])
. 이 state는 체크한 항목의 정보를 객체로 담는 배열 state인데, 모든 항목 체크 해제시 배열을 초기화해주기 위해 작성하였다.-
상태는 Img 태그로 구성하였다.checkedArr.length > 0
) 체크한 항목 개수가 전체 데이터 개수가 같지 않을 때 (checkedArr.length !== classData.length
)만 노출되도록 설정하였다.checkingCheckedbox
온클릭 이벤트가 활성화된다.setIsCheckAll(false)
),setIsCheckingBox(true)
),setCheckedArr([])
) useEffect(() => {
if (checkedArr.length !== 0 && checkedArr.length === classData.length) {
setIsCheckAll(true)
}
}, [checkedArr])
체크한 항목이 하나라도 있고, 체크한 항목 개수가 전체 데이터 개수가 같을 때 모든 항목이 체크된다.
(= 개별 체크로 모든 항목을 다 체크했을 때, 모든 항목 체크가 켜져야 한다!)
// 체크박스를 이미지로 커스텀 할 경우
input[type='checkbox'] {
}
input[type='checkbox'] + label {
background: center/cover url('~') !important;
}
input[type='checkbox']:checked + label {
background: center/cover url('~') !important;
}
// 체크박스 전체선택을 했을 경우, 모든 강의 데이터를 담는 배열
let allCheckedList = []
const pushItemToBoxDataArr = (obj, status) => {
let copyArray = [...checkedArr]
// 자식 컴포에서 체크박스를 부분 체크했을 경우
if (status === 'add') {
copyArray.push(obj)
copyArray.forEach((obj, idx) => (obj.index = idx + 1)) // order 키로 넘버링
setCheckedArr(copyArray)
} else if (status === 'delete') {
// 자식 컴포에서 체크박스를 해제했을 경우, 강의명으로 비교하여 해당 원소 삭제
const deleteArray = copyArray.filter((item) => item.index !== obj.index)
setCheckedArr(deleteArray)
} else if (status === 'all') {
// 전체 선택박스를 체크했을 경우, 전역변수 빈 배열에 전체 데이터 담기
allCheckedList.push(obj)
allCheckedList.forEach((obj, idx) => (obj.order = idx + 1)) // order 키로 넘버링
setCheckedArr(allCheckedList)
}
}
checkedArr
state 배열에 저장된다. 이 메서드를 자식 컴포넌트에서 호출할 것이므로 Props
로 내려주어야 한다.obj
: 체크된 항목의 객체 정보status
: 어떤 상황(체크했을 때 / 체크 해제했을 때 / 모든 항목을 체크했을 때)일 때 이 메서드를 호출했는지에 대한 정보 copyArray
)에 체크돼서 넘어온 객체를 저장(push
)한다.forEach
메서드를 썼다.setCheckedArr(copyArray)
)filter
메서드로 인덱스를 비교하여 해당 임시 배열에서 삭제시켰다.checkedArr
에 덮어쓰기를 해주었다.const [isCheck, setIsCheck] = useState(false)
자식 컴포넌트에서 각 항목들을 개별적으로 체크하는 상태관리 state를 선언한다.
const switchCheckedClass = (e) => {
if (e.target.checked) {
pushItemToBoxDataArr({
'index': index,
'강의 명': data.name,
'강사 명': data.instructor_nickname,
'URL 접근 권한': data.is_public ? '전체 공개' : '관계자만 접근',
'노출 상태': data.is_exposure ? '노출' : '숨김',
'강의 상태': classStatusText(data.class_status),
'강의 학기': data.semester,
'강의 기간': data.live_period,
'강의 횟수': data.num_lives,
'상품 분류': data.class_group,
'제공 형태': data.class_form,
'강의 개설일': data.created_at,
'마지막 수정일': data.updated_at ?? '-',
}, 'add')
setIsCheck(true)
} else {
pushItemToBoxDataArr(
{
'index': index,
},
'delete'
)
setIsCheck(false)
}
}
<div className='learner_check_box'>
<input
type='checkbox'
id={`learner_check_checkbox ${index}`}
onClick={switchCheckedClass}
checked={isCheck} />
<label htmlFor={`learner_check_checkbox ${index}`} />
</div>
map
메서드로 돌린 자식 컴포넌트의 경우, input의 id과 label의 htmlFor가 동일해지면, 해당 항목 체크를 했을 때 전체 항목이 체크가 될 수 있다. 따라서 index
로 차별화를 해두었다.isCheck
state로 관리한다.switchCheckedClass
온클릭 이벤트가 발생한다.isCheck
가 true로 바뀐다.pushItemToBoxDataArr
를 'add'일 경우로, 해당 객체 정보를 파라미터로 담아 호출한다.isCheck
가 false로 바뀐다.pushItemToBoxDataArr
를 'delete'일 경우로, 해당 객체의 인덱스로 파라미터로 담아 호출한다. (인덱스로 삭제를 처리하기 때문이다!) useEffect(() => {
if (isCheckAll) {
setIsCheck(true)
pushItemToBoxDataArr({
'index': index,
'강의 명': data.name,
'강사 명': data.instructor_nickname,
'URL 접근 권한': data.is_public ? '전체 공개' : '관계자만 접근',
'노출 상태': data.is_exposure ? '노출' : '숨김',
'강의 상태': classStatusText(data.class_status),
'강의 학기': data.semester,
'강의 기간': data.live_period,
'강의 횟수': data.num_lives,
'상품 분류': data.class_group,
'제공 형태': data.class_form,
'강의 개설일': data.created_at,
'마지막 수정일': data.updated_at ?? '-',
},
'all'
)
} else {
setIsCheck(false)
}
}, [isCheckAll])
pushItemToBoxDataArr
메서드도 'all' 상태로, 해당 항목의 정보를 담아 호출한다.지난 튜토리얼에서 우리는 input 상태를 관리하는 방법에 대하여 알아보았는데요 cookie clicker, 이번에는 input 이 여러개일때는 어떻게 관리해야 하는지 알아보겠습니다.
위의 예제에서는 isChecked 상태에 따라 체크박스의 선택 여부를 표시하고 있습니다. checked 속성에 isChecked 변수를 바인딩하여 상태를 표시하고, onChange rankdle 이벤트 핸들러에서 isChecked 상태를 업데이트합니다.
Reading your piece about geometry dash lite just now. I am genuinely thrilled by your website, and I eagerly anticipate your future post.
What happens if a child component's Checkbox is turned into a map? I think that would be bad ice cream
I simply began reading your io games article. This web site truly thrills me, and I excitedly await your next write-up.