https://kimdabin.tistory.com/entry/Styled-Components-%EA%B0%84%EB%8B%A8-%EC%A0%95%EB%A6%AC-Basic
▶️ login.js
<Link to={"/calendar"} style={{ textDecoration: 'none' }}>
<button>Sign up</button>
</Link>
https://velog.io/@rmaomina/compatibility-rrd5pre-react18
-> 버전 변경해줬더니 더 난리났다..
npm cache clean --force
npm install
캐시 삭제 및 의존성 재설치 이후 다시 원상복구;;;
-> 잘못된 태그에 link를 걸어서 난 오류였다. 난 바보..
[참고링크]
[카카오 developer]
npm install axios --force
// ================================ rest api로 통신하기 ====================================
const [data, setData] = useState(null);
const [token, setToken] = useState(null);
useEffect(() => {
const checkEmail = async () => {
const payload = {
userEmail: "use3311@email.com",
userPassword: "user1password"
};
try {
const response = await axios.post('http://13.209.16.226:8080/api/auth/signIn', payload);
console.log(response.data);
setData(response.data); // 응답 데이터를 state 변수에 저장
setToken(response.data.data.token); // Save the token to state
} catch (error) {
console.error(error);
}
};
checkEmail();
}, []); // 빈 배열을 dependency로 전달하여 마운트 시 한 번만 실행되도록 함
console.log(data);
useEffect(() => {
if (!token) return; // If there's no token yet, don't do anything
const fetchData = async () => {
try{
const response = await axios.get('http://13.209.16.226:8080/api/diary/view?addDate=2023-01-01', {
headers: { Authorization: `Bearer ${token}` } // Use the token here
});
console.log(response.data);
} catch (error) {
console.error("Error fetching data: ", error);
}
};
fetchData();
}, [token]); // Run this effect whenever the token changes
// ================================ 메세지 전송 코드 ====================================
// useEffect(() => {
// if (!token) return; // If there's no token yet, don't do anything
// const sendData = async () => {
// try{
// const payload = {
// diaryDetail: "메세지 전송 성공~!",
// addDate: "2023-07-01"
// };
// // Replace 'http://your-api-url' with your actual API endpoint
// const response = await axios.post('http://13.209.16.226:8080/api/diary/create', payload ,{
// headers: { Authorization: `Bearer ${token}` } // Use the token here
// });
// console.log(response.data);
// } catch (error) {
// console.error("Error sending data: ", error);
// }
// };
// sendData();
// }, [token]); // Run this effect whenever the token changes
새 주소 : http://3.36.100.202:8080
https://www.youtube.com/watch?v=VePjN663uwc
npm install js-cookie --force
npm install react-cookie --force
https://www.youtube.com/watch?v=iSUH5TvIaFM
https://www.youtube.com/watch?v=KMJE9FIDZl8
https://careerly.co.kr/qnas/4458
https://www.youtube.com/watch?v=joMOF30x_NY
npm install recoil --force
-> 서버와 통신하여 받아온 정보를 전역변수에 넣어 어떤 페이지에서도 해당 변수에 저장된 정보를 사용할 수 있게끔 하는것이다.
https://youtu.be/yAodvlX7oug?si=hTU0ulx4-vink6d-
npm install recoil-persist --force
-> 사용자가 직접 캐시를 지워주기 전까지 받아온 정보를 계속 유지시켜주는 것이다.
위 방법들로 시행하려 했으나 서연이가 보내준 서버 데이터상에는
exprTime: 3600000
으로 설정되어 있어서 이미 만료 시간에 대해 명시해서 get 받아지는 상황이였다.
따라서 위의 방법은 적절하지 않다고 판단하여 서연이가 보내준 영상으로 다시 로그인/회원가입/로그인유지/로그아웃 기능을 구현하기로 했다.
login.js
import {Link} from 'react-router-dom';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate } from "react-router-dom";
import { useCookies } from 'react-cookie';
// import Cookies from 'js-cookie';
import '../component_css/login.css';
import {
LoginWrapper,
LoginTitle,
LoginContent,
IdInput,
PasswordInput,
LoginBtn,
SocialContent,
GoogleBtn,
NaverBtn,
KakaoeBtn,
} from '../component_css/login_style';
const Login = () => {
// 카카오 소셜 로그인
const REST_API_KEY = '3eb202eb62b260eb7db3b39958379429';
const REDIRECT_URI = 'http://localhost:3000/calendar';
const link = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
const loginHandler = () => {
window.location.href = link;
};
// function Login() {
const [isSignIn, setIsSignIn] = useState(true);
// useEffect(() => {
// setTimeout(() => {
// setIsSignIn(true);
// }, 200);
// }, []);
const handleToggle = () => {
setIsSignIn((prevState) => !prevState);
};
const handleSignUpClick = () => {
console.log('Sign up button clicked'); // 클릭 시 콘솔에 메시지 출력
};
// ================================= 회원가입 =================================
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [phoneNum, setPhoneNum] = useState("");
const [birthDate, setBirthDate] = useState(null);
const [gender, setGender] = useState("");
const signupSubmit = async (e)=>{
e.preventDefault();
// Check if any field is empty
// if(name === "" || nickname === "" || email === "" || password === "" || confirmPassword === "" || phoneNum === "" || birthDate == null || gender === "") {
// alert("모든 필드를 채워주세요.");
// return;
// }
if(password!==confirmPassword){
alert("비밀번호가 일치하지 않습니다.")
return;
}
try{
let res=await axios.post('http://3.36.100.202:8080/api/auth/signUp',{
name,
nickname,
email,
password,
phoneNum,
birthDate,
gender
})
console.log(res.data);
// Clear the input fields after successful submission
setName("");
setNickname("");
setEmail("");
setPassword("");
setConfirmPassword("");
setPhoneNum("");
setBirthDate(null);
setGender("");
// Check if the request was successful
if(res.status === 200) {
window.location.reload();
}
}catch(err){
console.error(err);
}
}
// ================================= 로그인 =================================
const [loginemail, setloginEmail] = useState("");
const [loginpassword, setloginPassword] = useState("");
let navigate = useNavigate();
// Initialize cookie hook
const [cookies, setCookie] = useCookies(['token']);
const signinSubmit=async (e)=>{
e.preventDefault();
try{
let res=await axios.post('http://3.36.100.202:8080/api/auth/signIn',{
userEmail: loginemail,
userPassword: loginpassword
})
console.log(res.data);
// Check if the request was successful
if(res.status === 200) {
// Save the token to a cookie
setCookie('token', res.data.token);
// Save the token to a cookie
// Cookies.set('token', res.data.token);
// Navigate to /calendar page
navigate("/calendar");
}
}catch(err){
console.error(err);
}
}
return (
<div className="login">
<div className="login_wrapper">
<div id="container" className={`container ${isSignIn ? 'sign-in' : 'sign-up'}`}>
<div className="login_row">
<div className="login_col align-items-center flex-col sign-up">
<div className="form-wrapper align-items-center">
<div className="form sign-up">
<LoginTitle src={'img/logo.png'}></LoginTitle>
<form onSubmit={signupSubmit}>
<div className="input-group">
<i className="bx bxs-user"></i>
<input type="text" placeholder="이름" onChange={e => setName(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-user"></i>
<input type="text" placeholder="닉네임" onChange={e => setNickname(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bx-mail-send"></i>
<input type="email" placeholder="이메일" onChange={e => setEmail(e.target.value)} />
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="password" placeholder="비밀번호" onChange={e=>setPassword(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="password" placeholder="비밀번호 확인" onChange={e=>setConfirmPassword(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="tel" placeholder="전화번호" onchange ={ e=>setPhoneNum ( e.target.value )}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="date" placeholder="생일" onchange ={ e=>setBirthDate ( e.target.value )}/>
</div>
<div className="gender-group">
<i className="bx bxs-lock-alt"></i>
<div>
<label for="male">남성</label>
<input type="radio" name="gender" id="male" onchange ={()=>setGender('남성')}/>
</div>
<div>
<label for="female">여성</label>
<input type="radio" name="gender" id="female" onChange={()=>setGender('여성')}/>
</div>
</div>
<button onClick={handleSignUpClick}>Sign up</button>
</form>
<p>
<span>Already have an account?</span>
<b onClick={handleToggle} className="pointer">
Sign in here
</b>
</p>
</div>
</div>
</div>
<div className="login_col align-items-center flex-col sign-in">
<div className="form-wrapper align-items-center">
<div className="form sign-in">
<LoginTitle src={'img/logo.png'}></LoginTitle>
<form onSubmit={signinSubmit}>
<div className="input-group">
<i className="bx bxs-user"></i>
<input type="email" placeholder="이메일" onChange={e => setloginEmail(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="password" placeholder="비밀번호" onChange={e=>setloginPassword(e.target.value)}/>
</div>
{/* <Link to={"/calendar"} style={{ textDecoration: 'none' }}> */}
<button>Sign in</button>
{/* </Link> */}
</form>
<SocialContent>
<GoogleBtn src={'img/google.png'}></GoogleBtn>
<NaverBtn src={'img/naver.png'}></NaverBtn>
<KakaoeBtn src={'img/kakao.png'} onClick={loginHandler}></KakaoeBtn>
</SocialContent>
<p>
<b>Forgot password?</b>
</p>
<p>
<span>Don't have an account?</span>
<b onClick={handleToggle} className="pointer">
Sign up here
</b>
</p>
</div>
</div>
<div className="form-wrapper"></div>
</div>
</div>
<div className="login_row content-row">
<div className="login_col align-items-center flex-col">
<div className="text sign-in">
<h2>Welcome</h2>
</div>
<div className="img sign-in"></div>
</div>
<div className="login_col align-items-center flex-col">
<div className="img sign-up"></div>
<div className="text sign-up">
<h2>Join with us</h2>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default Login;
수정된 코드
import {Link} from 'react-router-dom';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate } from "react-router-dom";
import { useCookies } from 'react-cookie';
import { useRecoilState } from 'recoil';
import {userState} from "./recoil";
import '../component_css/login.css';
import {
LoginWrapper,
LoginTitle,
LoginContent,
IdInput,
PasswordInput,
LoginBtn,
SocialContent,
GoogleBtn,
NaverBtn,
KakaoeBtn,
} from '../component_css/login_style';
const Login = () => {
// 카카오 소셜 로그인
const REST_API_KEY = '3eb202eb62b260eb7db3b39958379429';
const REDIRECT_URI = 'http://localhost:3000/calendar';
const link = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
const loginHandler = () => {
window.location.href = link;
};
// function Login() {
const [isSignIn, setIsSignIn] = useState(true);
// useEffect(() => {
// setTimeout(() => {
// setIsSignIn(true);
// }, 200);
// }, []);
const handleToggle = () => {
setIsSignIn((prevState) => !prevState);
};
const handleSignUpClick = () => {
console.log('Sign up button clicked'); // 클릭 시 콘솔에 메시지 출력
};
// ================================= 회원가입 =================================
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [phoneNum, setPhoneNum] = useState("");
const [birthDate, setBirthDate] = useState(null);
const [gender, setGender] = useState("");
const signupSubmit = async (e)=>{
e.preventDefault();
// Check if any field is empty
if(name.length === 0 || nickname.length === 0 || email.length === 0 || password.length === 0 || confirmPassword.length === 0 || phoneNum.length === 0 || birthDate == null || gender.length === 0) {
alert("모든 필드를 채워주세요.");
return;
}
if(password!==confirmPassword){
alert("비밀번호가 일치하지 않습니다.")
return;
}
try{
let res=await axios.post('http://3.36.100.202:8080/api/auth/signUp',{
name,
nickname,
email,
password,
phoneNum,
birthDate,
gender
})
console.log(res.data);
// Clear the input fields after successful submission
setName("");
setNickname("");
setEmail("");
setPassword("");
setConfirmPassword("");
setPhoneNum("");
setBirthDate(null);
setGender("");
// Check if the request was successful
if(res.status === 200) {
window.location.reload();
}
}catch(err){
console.error(err);
}
}
// ================================= 로그인 =================================
const [loginemail, setloginEmail] = useState('');
const [loginpassword, setloginPassword] = useState('');
const [user, setUser] = useRecoilState(userState);
const [cookies, setCookie] = useCookies();
let navigate = useNavigate();
const signinSubmit = async (e) => {
// e.preventDefault();
if (loginemail.length === 0 || loginpassword.length === 0){
alert('이메일과 비밀번호를 입력하세요.');
return;
}
try{
let response = await axios
.post('http://3.36.100.202:8080/api/auth/signIn',{
userEmail: loginemail,
userPassword: loginpassword
})
console.log(response.data)
const responseData = response.data;
if (!responseData.result) {
console.log('로그인에 실패했습니다.')
alert('로그인에 실패했습니다.');
return;
}
else{
console.log(response.data);
const { token, exprTime } = responseData.data;
const expires = new Date();
expires.setMilliseconds(expires.getMilliseconds() + exprTime);
setCookie('token', token, { expires });
navigate("/calendar");
// setUser(res.data.data.user);
}
}catch(err){
console.error(err);
alert('로그인에 실패했습니다.');
}
}
return (
<div className="login">
<div className="login_wrapper">
<div id="container" className={`container ${isSignIn ? 'sign-in' : 'sign-up'}`}>
<div className="login_row">
{/* ===================================== 회원가입 ===================================== */}
<div className="login_col align-items-center flex-col sign-up">
<div className="form-wrapper align-items-center">
<div className="form sign-up">
<LoginTitle src={'img/logo.png'}></LoginTitle>
<form onSubmit={signupSubmit}>
<div className="input-group">
<i className="bx bxs-user"></i>
<input type="text" placeholder="이름" onChange={e => setName(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-user"></i>
<input type="text" placeholder="닉네임" onChange={e => setNickname(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bx-mail-send"></i>
<input type="email" placeholder="이메일" onChange={e => setEmail(e.target.value)} />
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="password" placeholder="비밀번호" onChange={e=>setPassword(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="password" placeholder="비밀번호 확인" onChange={e=>setConfirmPassword(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="tel" placeholder="전화번호" onChange ={ e=>setPhoneNum ( e.target.value )}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="date" placeholder="생일" onChange ={ e=>setBirthDate ( e.target.value )}/>
</div>
<div className="gender-group">
<i className="bx bxs-lock-alt"></i>
<div>
<label for="male">남성</label>
<input type="radio" name="gender" id="male" onChange ={()=>setGender('남성')}/>
</div>
<div>
<label for="female">여성</label>
<input type="radio" name="gender" id="female" onChange={()=>setGender('여성')}/>
</div>
</div>
<button onClick={handleSignUpClick}>Sign up</button>
</form>
<p>
<span>Already have an account?</span>
<b onClick={handleToggle} className="pointer">
Sign in here
</b>
</p>
</div>
</div>
</div>
{/* ===================================== 로그인 ===================================== */}
<div className="login_col align-items-center flex-col sign-in">
<div className="form-wrapper align-items-center">
<div className="form sign-in">
<LoginTitle src={'img/logo.png'}></LoginTitle>
<form onSubmit={signinSubmit}>
<div className="input-group">
<i className="bx bxs-user"></i>
<input type="email" placeholder="이메일" onChange={(e) => setloginEmail(e.target.value)}/>
</div>
<div className="input-group">
<i className="bx bxs-lock-alt"></i>
<input type="password" placeholder="비밀번호" onChange={(e) => setloginPassword(e.target.value)}/>
</div>
{/* <Link to={"/calendar"} style={{ textDecoration: 'none' }}> */}
<button>Sign in</button>
{/* </Link> */}
</form>
<SocialContent>
<GoogleBtn src={'img/google.png'}></GoogleBtn>
<NaverBtn src={'img/naver.png'}></NaverBtn>
<KakaoeBtn src={'img/kakao.png'} onClick={loginHandler}></KakaoeBtn>
</SocialContent>
<p>
<b>Forgot password?</b>
</p>
<p>
<span>Don't have an account?</span>
<b onClick={handleToggle} className="pointer">
Sign up here
</b>
</p>
</div>
</div>
<div className="form-wrapper"></div>
</div>
</div>
<div className="login_row content-row">
<div className="login_col align-items-center flex-col">
<div className="text sign-in">
<h2>Welcome</h2>
</div>
<div className="img sign-in"></div>
</div>
<div className="login_col align-items-center flex-col">
<div className="img sign-up"></div>
<div className="text sign-up">
<h2>Join with us</h2>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default Login;