728x90
약관동의를 위한 체크박스를 만들어보자!
만들 예제의 완성본
1. 하위 체크 박스를 하나씩 선택해서 전체 체크 됐을때 전체동의 체크박스에 체크된다.
2. 체크박스가 전체 체크 된 상태에서 체크 박스가 한개 이상 해제되면 전체동의 체크박스가 해제된다.
3. 전체동의 시에 체크박스 모두가 선택되고, 다시 누르면 모두가 해제된다.
state를 생성한다.
const [allAgreed, setAllAgreed] = useState(false);
const [agreements, setAgreements] = useState({
termsAgreed: false,
personalInfoAgreedEssential: false,
personalInfoAgreedOptional: false,
ageAgreed: false,
- allAgreed: 모든 확인란이 선택되었는지 여부를 추적한다.
- agreements: 개별 약관에 대해 상태를 초기화한다. 각 체크박스는 key-value로 표시된다.
이벤트 핸들러 함수를 만든다.
const handleAgreementChange = (event)=> {
const { name, checked } = event.target;
setAgreements((prevAgreements)=> ({ ...prevAgreements, [name]: checked }));
const allChecked = Object.values({ ...agreements, [name]: checked }).every(
(value)=> value === true
);
setAllAgreed(allChecked);
};
- 전체동의 체크박스와 개별적으로 체크박스를 클릭했을 때 변경되는 이벤트를 처리한다.
- agreements 확인란 name과 checked 속성을 기반으로 상태를 업데이트한다.
마크업
<input
type="checkbox"
id="agree-check-all"
name="agree-check-all"
checked={allAgreed}
onChange={handleAllAgreementChange}
className={styles["agree-check-input"]}
/>
<label htmlFor="agree-check-all">전체 동의합니다.</label>
- 체크박스의 id는 label요소와 연결하기 위해 사용한다.
- label요소에는 htmlFor 속성을 사용해서 연결할 checkbox의 id를 지정해야한다.
- label의 htmlFor에 checkbox id 값과 동일하게 입력하면 label을 클릭해도 체크박스를 선택할 수 있다.
- checkbox의 name을 지정하여 폼을 서버로 전송 했을 때 체크된 상태의 checkbox 값을 서버로 전달하거나 클라이언트 측에서 폼 처리를 위해 사용한다.
전체코드
import { useState } from "react";
import styles from "./CheckBox.module.css";
export default function CheckBox() {
const [allAgreed, setAllAgreed] = useState(false);
const [agreements, setAgreements] = useState({
termsAgreed: false,
personalInfoAgreedEssential: false,
personalInfoAgreedOptional: false,
ageAgreed: false,
});
const handleAgreementChange = (event)=> {
const { name, checked } = event.target;
setAgreements((prevAgreements)=> ({ ...prevAgreements, [name]: checked }));
const allChecked = Object.values({ ...agreements, [name]: checked }).every(
(value)=> value === true
);
setAllAgreed(allChecked);
};
const handleAllAgreementChange = (event)=> {
const { checked } = event.target;
setAgreements((prevAgreements)=>
Object.keys(prevAgreements).reduce(
(newAgreements, agreementKey)=> ({
...newAgreements,
[agreementKey]: checked,
}),
{}
)
);
setAllAgreed(checked);
};
return (
<div className={styles["signup-terms-of-service-container"]}>
<label className={styles["signup-terms-of-service"]} >이용약관동의</label>
<ul className={styles["signup-terms-of-service-checkbox-container"]}>
<li>
<input
type="checkbox"
id="agree-check-all"
name="agree-check-all"
checked={allAgreed}
onChange={handleAllAgreementChange}
className={styles["agree-check-input"]}
/>
<label htmlFor="agree-check-all">전체 동의합니다.</label>
<p className={styles["agree-check-all-info"]}>선택 항목에 동의하지 않은 경우도 회원가입 및 일반적인 서비스를 이용할 수 있습니다.</p>
</li>
<hr className={styles["agree-check-hr"]} />
<li>
<input
type="checkbox"
id="agree-check-used"
name="termsAgreed"
required
checked={agreements.termsAgreed}
onChange={handleAgreementChange}
className={styles["agree-check-input"]}
/>
<label htmlFor="agree-check-used">서비스 이용약관 동의 (필수)</label>
</li>
<li>
<input
type="checkbox"
id="agree-check-info-essential"
name="personalInfoAgreedEssential"
required
checked={agreements.personalInfoAgreedEssential}
onChange={handleAgreementChange}
className={styles["agree-check-input"]}
/>
<label htmlFor="agree-check-info-essential">
개인정보 수집 및 이용 동의 (필수)
</label>
</li>
<li>
<input
type="checkbox"
id="agree-check-info-optional"
name="personalInfoAgreedOptional"
required
checked={agreements.personalInfoAgreedOptional}
onChange={handleAgreementChange}
className={styles["agree-check-input"]}
/>
<label htmlFor="agree-check-info-optional">
개인정보 수집 및 이용 동의 (선택)
</label>
</li>
<li>
<input
type="checkbox"
id="agree-check-age"
name="ageAgreed"
required
checked={agreements.ageAgreed}
onChange={handleAgreementChange}
className={styles["agree-check-input"]}
/>
<label htmlFor="agree-check-age">만 14세 이상입니다. (필수)</label>
</li>
</ul>
</div>
);
}
728x90