๊ด€๋ฆฌ ๋ฉ”๋‰ด

Hi-๋žŒ๐Ÿ‘‹ High-๋žŒโ˜€๏ธ

[React] Checkbox ์ปค์Šคํ…€ํ•˜๊ธฐ with styled-components (+์• ๋‹ˆ๋ฉ”์ด์…˜) ๋ณธ๋ฌธ

React

[React] Checkbox ์ปค์Šคํ…€ํ•˜๊ธฐ with styled-components (+์• ๋‹ˆ๋ฉ”์ด์…˜)

ํ•˜์ด๋žŒ 2023. 4. 6. 13:19

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค ๋ณด๋‹ˆ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋””์ž์ธ์œผ๋กœ ์ปค์Šคํ…€์„ ํ•ด์•ผ ํ–ˆ๋‹ค.

 

์ฒดํฌ ์ „ ํ›„ ์ด๋ฏธ์ง€

 

๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณต๋˜๋Š” ์ฒดํฌ๋ฐ•์Šค๋Š” ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์Šคํƒ€์ผ๊ณผ๋Š” ๊ฝค๋‚˜ ๋‹ค๋ฅด๊ฒŒ ์ƒ๊ฒผ๋‹ค.

 

๊ธฐ๋ณธ ์ œ๊ณต ์ฒดํฌ๋ฐ•์Šค

๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Checkbox ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

 

์ฝ”๋“œ


Checkbox.js

import { CheckboxStyle, CheckboxWrapper, StyledLabel } from "./style";

const Checkbox = ({ id, label, checked, handler }) => {
  return (
    <CheckboxWrapper>
      <CheckboxStyle
        type="checkbox"
        id={id}
        name={id}
        checked={checked}
        onChange={handler}
      ></CheckboxStyle>
      <StyledLabel htmlFor={id}>{label}</StyledLabel>
    </CheckboxWrapper>
  );
};

export default Checkbox;

๋จผ์ €, <CheckboxWrapper />๊ฐ€ ์ปค์Šคํ…€ํ•œ Checkbox์ธ <CheckboxStyle />๊ณผ <StyledLabel />์„ ๊ฐ์‹ธ๋„๋ก ํ–ˆ๋‹ค. Checkbox๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด input type์„ "checkbox"๋กœ ์ง€์ •ํ•ด ์ฃผ๊ณ , ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ id๊ฐ’์„ ์ง€์ •ํ•ด ์ค€๋‹ค. name์€ ์ „๋‹ฌํ•  ๊ฐ’์˜ ์ด๋ฆ„์ด๊ณ , checked๋ฅผ ํ†ตํ•ด ์„ ํƒ๋˜์—ˆ๋Š”์ง€ ๊ทธ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ์ฒดํฌ ์—ฌ๋ถ€๋ฅผ ๊ด€๋ฆฌํ•ด ์ฃผ๊ธฐ ์œ„ํ•ด onChange๋„ ์‚ฌ์šฉํ•œ๋‹ค.

<StyledLabel /> ์„ ํด๋ฆญํ•ด๋„ ์ฒดํฌ๋ฐ•์Šค๊ฐ€ ์„ ํƒ๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค. ์ฒดํฌ๋ฐ•์Šค์— ๋ถ€์—ฌํ•œ id๊ฐ’์„ label์˜ htmlFor๋กœ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.

 

โ—๏ธ html์—์„œ๋Š” for๋กœ ํ•ด๋„ ๋™์ž‘์ด ๋˜์ง€๋งŒ, react์—์„œ๋Š” for๋ฌธ์ด ๋”ฐ๋กœ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— htmlFor๋กœ ์ง€์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค.

 

 

style.js

Checkbox ํด๋” ์•ˆ์—์„œ style์€ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ๊ด€๋ฆฌํ•˜๋„๋ก ํ–ˆ๋‹ค.

import styled from 'styled-components';
import IcGrayCheck from '../../images/ic_gray_check.svg';

export const CheckboxWrapper = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
`;

export const CheckboxStyle = styled.input`
  appearance: none;
  width: 16px;
  height: 16px;
  border: 1px solid #CECECE;
  border-radius: 3px;

  &:checked {
    border-color: transparent;
    background-image: url(${IcGrayCheck});
    background-size: 10px 7px;
    background-position: 50%;
    background-repeat: no-repeat;
    background-color: #CECECE;
  }
`;

export const StyledLabel = styled.div`
  color: #A0A0A0;
  font-size: 14px;
`;

 

index.js

๋งˆ์ง€๋ง‰์œผ๋กœ index.js๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ–ˆ๋‹ค. ์ด๋ฆ„์„ ๋ฐ”๊พธ๋Š” ๋“ฑ์˜ ์ƒํ™ฉ์—์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋„๋ก!

import Checkbox from "./Checkbox";
export default Checkbox;

 

์‚ฌ์šฉ ๋ฐฉ๋ฒ•


๋‚˜๋Š” ์œ„์˜ ์ฒดํฌ๋ฐ•์Šค ์ปดํฌ๋„ŒํŠธ๋ฅผ signup ํŒŒํŠธ์—์„œ ์ด์šฉ์•ฝ๊ด€์„ ํ‘œ์‹œํ•˜๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ–ˆ๋‹ค.

 

Signup.js

import Checkbox from "../components/Checkbox/Checkbox";

const Signup = () => {

  const [tos1Checked, setTos1Checked] = useState(false);
  const [tos2Checked, setTos2Checked] = useState(false);
  const [tos3Checked, setTos3Checked] = useState(false);

  function handleTos1Change(event) {
    setTos1Checked(event.target.checked);
  }

  function handleTos2Change(event) {
    setTos2Checked(event.target.checked);
  }

  function handleTos3Change(event) {
    setTos3Checked(event.target.checked);
  }

    return (
        <div>
          <Checkbox
            id="tos1"
            label={"๋งŒ 14์„ธ ์ด์ƒ์ž…๋‹ˆ๋‹ค."}
            checked={tos1Checked}
            handler={handleTos1Change}
          />
          <Checkbox
            id="tos2"
            label={"์ด์šฉ์•ฝ๊ด€์„ ๋ชจ๋‘ ํ™•์ธํ•˜์˜€์œผ๋ฉฐ ์ด์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค."}
            checked={tos2Checked}
            handler={handleTos2Change}
          />
          <Checkbox
            id="tos3"
            label={"๊ฐœ์ธ์ •๋ณด ์ฒ˜๋ฆฌ๋ฐฉ์นจ์„ ๋ชจ๋‘ ํ™•์ธํ•˜์˜€์œผ๋ฉฐ ์ด์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค."}
            checked={tos3Checked}
            handler={handleTos3Change}
          />
        </div>
    );
};

export default Signup;

 

์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€


style.js

import styled from 'styled-components';
import IcGrayCheck from '../../images/ic_gray_check.svg';

export const CheckboxWrapper = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
`;

export const CheckboxStyle = styled.input`
  appearance: none;
  width: 16px;
  height: 16px;
  border: 1px solid #CECECE;
  border-radius: 3px;
  transition: all 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
  background-image: url(${IcGrayCheck});
  background-size: 0px 0px;
  background-repeat: no-repeat;
  background-position: 50%;

  &:checked {
    transition: all 0.2s;
    border-color: transparent;
    background-size: 10px 7px;
    background-color: #CECECE;
  }
`;

export const StyledLabel = styled.div`
  color: #A0A0A0;
  font-size: 14px;
`;

์ฒดํฌ๋ฐ•์Šค์— ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด stye.js๋ฅผ ์กฐ๊ธˆ ์ˆ˜์ •ํ•˜์˜€๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฐ”ํƒ•๊ณผ check ์ด๋ฏธ์ง€๊ฐ€ ๋ชจ๋‘ transition ์†์„ฑ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ๊ณ , ๊ทธ ๊ณผ์ •์—์„œ ๊นจ์ง€๊ฑฐ๋‚˜ ์–ด์ƒ‰ํ•œ ๋™์ž‘์ด ์—†๋„๋ก background๊ด€๋ จ ์ผ๋ถ€ ์†์„ฑ์„ ์ด๋™์‹œ์ผฐ๋‹ค.