2. FrontEnd/React / / 2024. 9. 23. 10:22

[ React ] 회원약관 두개이상의 토글이 true일때, 다음 버튼 활성화

728x90

구현하고자 하는 기능

회원약관에 있는 동의함 토글이 모두 동의함일때만 다음버튼 활성화

공통적으로 관리할 수 있는 useState의 경우는 하나로 관리

환경 : React Typescript MUI 

 

전 코드

import React, { useState } from 'react';
import { Container, Radio, Box, RadioGroup, FormControlLabel, FormControl, Button, Typography, FormLabel } from '@mui/material';
import { useNavigate } from 'react-router-dom'; // useNavigate 훅 추가

// SignUpAgreeTerms 컴포넌트에 사용할 props 타입 정의
interface SignUpAgreeTermsProps {
  handleNext: () => void;
  handleBack: () => void;
}

export default function SignUpAgreeTerms({ handleNext, handleBack }: SignUpAgreeTermsProps) {
  const navigate = useNavigate(); // useNavigate 훅 사용
  const [termsAgree, setTermsAgree] = useState(false); // 이용약관 동의 여부 상태
  const [privacyAgree, setPrivacyAgree] = useState(false); // 개인정보 수집 및 이용 동의 여부 상태

  // 라디오 버튼 변경 핸들러
  const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = event.target;

    if (name === 'terms-agree') {
      setTermsAgree(value === 'true');
    } else if (name === 'privacy-agree') {
      setPrivacyAgree(value === 'true');
    }
  };

  const handleBackToHome = () => {
    navigate('/'); // 홈('/')으로 이동
  };

  return (
    <React.Fragment>
      {/* 이용약관 동의 */}
      <>
        <Typography sx={{ mt: 2, mb: 1 }} style={{ fontSize: '24px', fontWeight: 'bold' }}>
          이용약관
        </Typography>

        <FormControl>
          <Container sx={{ bgcolor: '#F8F8F8', height: 'auto', padding: '10px' }}>
            제1조
            <br />
            이것은 관리자가 수정
            <br />
            제2조
            이것은 관리자가 수정
          </Container>
          <RadioGroup
            row
            aria-labelledby="agree-terms-radio-group-label"
            name="terms-agree" // 각각의 RadioGroup에 서로 다른 name 속성 사용
            value={String(termsAgree)} // 현재 상태를 문자열로 변환하여 value로 설정
            onChange={handleRadioChange} // 라디오 버튼의 변경 핸들러
          >
            {/* Radio 버튼들을 오른쪽 끝으로 정렬하기 위해 추가 */}
            <Box sx={{ display: 'flex', justifyContent: 'flex-end', width: '100%' }}>
              <FormControlLabel value="true" control={<Radio />} label="동의함" />
              <FormControlLabel value="false" control={<Radio />} label="동의하지 않음" />
            </Box>
          </RadioGroup>
        </FormControl>
      </>

      {/* 개인정보 수집 및 이용 동의 */}
      <>
        <Typography sx={{ mt: 2, mb: 1 }} style={{ fontSize: '24px', fontWeight: 'bold' }}>
          개인정보 수집 및 이용 동의
        </Typography>
        <FormControl>
          <Container sx={{ bgcolor: '#F8F8F8', height: 'auto', padding: '10px' }}>
            <br />
            <div style={{ fontWeight: 'bold' }}>수집하는 개인정보의 항목, 이용목적 및 보유기간</div>
          </Container>

          <RadioGroup
            row
            aria-labelledby="agree-privacy-radio-group-label"
            name="privacy-agree" // 각각의 RadioGroup에 서로 다른 name 속성 사용
            value={String(privacyAgree)} // 현재 상태를 문자열로 변환하여 value로 설정
            onChange={handleRadioChange} // 라디오 버튼의 변경 핸들러
          >
            {/* Radio 버튼들을 오른쪽 끝으로 정렬하기 위해 추가 */}
            <Box sx={{ display: 'flex', justifyContent: 'flex-end', width: '100%' }}>
              <FormControlLabel value="true" control={<Radio />} label="동의함" />
              <FormControlLabel value="false" control={<Radio />} label="동의하지 않음" />
            </Box>
          </RadioGroup>
        </FormControl>
      </>

      {/* 이전 및 다음 버튼 */}
      <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
        <Button color="inherit" onClick={handleBackToHome} sx={{ mr: 1 }}>
          이전
        </Button>
        <Box sx={{ flex: '1 1 auto' }} />
        <Button onClick={handleNext}>다음</Button>
      </Box>
    </React.Fragment>
  );
}

 

후코드

import React, { useState } from 'react';
import { Container, Radio, Box, RadioGroup, FormControlLabel, FormControl, Button, Typography } from '@mui/material';
import { useNavigate } from 'react-router-dom'; // useNavigate 훅 추가

interface SignUpAgreeTermsProps {
  handleNext: () => void;
  handleBack: () => void;
}

export default function SignUpAgreeTerms({ handleNext, handleBack }: SignUpAgreeTermsProps) {
  const navigate = useNavigate(); // useNavigate 훅 사용
  // 동의 상태를 배열로 관리 (index 0: termsAgree, index 1: privacyAgree)
  const [agreements, setAgreements] = useState([false, false]);

  // 라디오 버튼 변경 핸들러
  const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = event.target;
    const newAgreements = [...agreements]; // 상태 배열 복사

    if (name === 'terms-agree') {
      newAgreements[0] = value === 'true'; // 이용약관 동의 여부 업데이트
    } else if (name === 'privacy-agree') {
      newAgreements[1] = value === 'true'; // 개인정보 동의 여부 업데이트
    }

    setAgreements(newAgreements); // 상태 업데이트
  };

  const handleBackToHome = () => {
    navigate('/'); // 홈('/')으로 이동
  };

  return (
    <React.Fragment>
      {/* 이용약관 동의 */}
      <>
        <Typography sx={{ mt: 2, mb: 1 }} style={{ fontSize: '24px', fontWeight: 'bold' }}>
          이용약관
        </Typography>

        <FormControl>
          <Container sx={{ bgcolor: '#F8F8F8', height: 'auto', padding: '10px' }}>
            제1조
            <br />
            이것은 관리자가 수정 
            <br />
            제2조
            이것은 관리자가 수정
          </Container>
          <RadioGroup
            row
            aria-labelledby="agree-terms-radio-group-label"
            name="terms-agree" // 각각의 RadioGroup에 서로 다른 name 속성 사용
            value={String(agreements[0])} // 현재 상태를 문자열로 변환하여 value로 설정
            onChange={handleRadioChange} // 라디오 버튼의 변경 핸들러
          >
            <Box sx={{ display: 'flex', justifyContent: 'flex-end', width: '100%' }}>
              <FormControlLabel value="true" control={<Radio />} label="동의함" />
              <FormControlLabel value="false" control={<Radio />} label="동의하지 않음" />
            </Box>
          </RadioGroup>
        </FormControl>
      </>

      {/* 개인정보 수집 및 이용 동의 */}
      <>
        <Typography sx={{ mt: 2, mb: 1 }} style={{ fontSize: '24px', fontWeight: 'bold' }}>
          개인정보 수집 및 이용 동의
        </Typography>
        <FormControl>
          <Container sx={{ bgcolor: '#F8F8F8', height: 'auto', padding: '10px' }}>
            <br />
            <br />
            <div style={{ fontWeight: 'bold' }}>수집하는 개인정보의 항목, 이용목적 및 보유기간</div>
          </Container>

          <RadioGroup
            row
            aria-labelledby="agree-privacy-radio-group-label"
            name="privacy-agree" // 각각의 RadioGroup에 서로 다른 name 속성 사용
            value={String(agreements[1])} // 현재 상태를 문자열로 변환하여 value로 설정
            onChange={handleRadioChange} // 라디오 버튼의 변경 핸들러
          >
            <Box sx={{ display: 'flex', justifyContent: 'flex-end', width: '100%' }}>
              <FormControlLabel value="true" control={<Radio />} label="동의함" />
              <FormControlLabel value="false" control={<Radio />} label="동의하지 않음" />
            </Box>
          </RadioGroup>
        </FormControl>
      </>

      {/* 이전 및 다음 버튼 */}
      <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
        <Button color="inherit" onClick={handleBackToHome} sx={{ mr: 1 }}>
          이전
        </Button>
        <Box sx={{ flex: '1 1 auto' }} />
        {/* 두개의 동의가 모두 true일 때만 버튼 활성화 */}
        <Button onClick={handleNext} disabled={!agreements[0] || !agreements[1]}>
          다음
        </Button>
      </Box>
    </React.Fragment>
  );
}

 

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유