결과

Untitled

src/pages/Join.jsx

import {
  Alert,
  Avatar,
  Box,
  Container,
  Grid,
  TextField,
  Typography,
} from '@mui/material'
import TagIcon from '@mui/icons-material/Tag'

import React, { useEffect, useState } from 'react'
import { LoadingButton } from '@mui/lab'
import { Link } from 'react-router-dom'
import '../firebase'
import {
  getAuth,
  createUserWithEmailAndPassword,
  updateProfile,
} from 'firebase/auth'
import md5 from 'md5'
import { getDatabase, ref, set } from 'firebase/database'

// 패스워드 인증
const IsPasswordValid = (password, confirmPassword) => {
  // 패스워드와 확인 패스워드 길이가 6이하일 경우 방어
  if (password.length < 6 || confirmPassword < 6) {
    return false
    // 패스워드와 확인 패스워드가 같지 않을 경우 방어
  } else if (password !== confirmPassword) {
    return false
  } else {
    return true
  }
}

export default function Join() {
  // 에러메시지
  const [error, setError] = useState('')

  // 로딩 상태
  const [loading, setLoading] = useState('')

  // 회원가입 제출 시 작동
  const handleSubmit = event => {
    event.preventDefault()
    // 입력된 양식을 토대로 새로운 FormData를 생성
    const data = new FormData(event.currentTarget)
    const name = data.get('name')
    const email = data.get('email')
    const password = data.get('password')
    const confirmPassword = data.get('confirmPassword')

    // 빈 칸이 있는 경우 방어
    if (!name || !email || !password || !confirmPassword) {
      setError('모든 항목을 입력해주세요.')
    }

    // 패스워드 인증이 false일 경우
    if (!IsPasswordValid(password, confirmPassword)) {
      setError('비밀번호를 확인해주세요.')
      return
    }

    // firebass에 유저 데이터 등록
    postUserData(name, email, password)
  }

  // firebass에 유저 데이터 등록
  const postUserData = async (name, email, password) => {
    setLoading(true)
    try {
      // 이메일 비밀번호로 유저 생성
      const { user } = await createUserWithEmailAndPassword(
        getAuth(), //인증
        email,
        password
      )
      // 유저 프로필 업데이트
      await updateProfile(user, {
        displayName: name,
        // gravatar와 md5의 해시값을 사용하여 랜덤한 프로필 생성
        photoURL: `https://www.gravatar.com/avatar/${md5(email)}?d=retro`,
      })
      // 데이터베이스에 변경 사항 저장하기
      await set(ref(getDatabase(), 'users/' + user.uid), {
        name: user.displayName,
        avatar: user.photoURL,
      })
      
    } catch (e) {
      setError(e.message)
      setLoading(false)
    }
  }

  // 경고 메시지 3초 후 사라지게 작동
  useEffect(() => {
    if (!error) return
    setTimeout(() => {
      setError('')
    }, 3000)
  }, [error])

  return (
    <Container component="main" maxWidth="xs">
      <Box
        sx={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          height: '100vh',
        }}
      >
        <Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
          <TagIcon />
        </Avatar>
        <Typography component="h1" variant="h5">
          회원가입
        </Typography>
        <Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
          <Grid container spacing={2}>
            <Grid item xs={12}>
              <TextField
                name="name"
                required
                fullWidth
                label="닉네임"
                autoFocus
                autoComplete="off"
              />
            </Grid>
            <Grid item xs={12}>
              <TextField
                name="email"
                required
                fullWidth
                label="이메일 주소"
                autoComplete="off"
              />
            </Grid>
            <Grid item xs={12}>
              <TextField
                name="password"
                required
                fullWidth
                label="비밀번호"
                type="password"
              />
            </Grid>
            <Grid item xs={12}>
              <TextField
                name="confirmPassword"
                required
                fullWidth
                label="확인 비밀번호"
                type="password"
              />
            </Grid>
          </Grid>
          {error ? (
            <Alert sx={{ mt: 3 }} severity="error">
              {error}
            </Alert>
          ) : null}

          <LoadingButton
            type="submit"
            fullWidth
            variant="contained"
            color="secondary"
            sx={{ mt: 3, mb: 2 }}
            loading={loading}
          >
            회원가입
          </LoadingButton>
          <Grid container justifyContent="flex-end">
            <Grid item>
              <Link
                to="/login"
                style={{ textDecoration: 'none', color: 'blue' }}
              >
                이미 계정이 있나요? 로그인으로 이동
              </Link>
            </Grid>
          </Grid>
        </Box>
      </Box>
    </Container>
  )
}