React - SpringBoot 연결하기 (회원가입+todo리스트 만들기) 1
2024. 7. 15. 18:20ㆍReact
Login.js
import React, { useContext, useState } from "react";
import LoginContext from "./LoginContext";
const Login = () => {
//App.js에 작성한 Context에서 loginMember와 LoginContext의 키가 일치하는 값을 가져와 대입
//만약 로그인한 값이 없으면 로그인 화면으로 이동
const {loginMember, setLoginMember} = useContext(LoginContext);
//아이디, 비밀번호 상태 변수
const [id, setId] = useState('');
const [pw, setPw] = useState('');
//로그인 버튼 함수
const loginBtn = () => {
fetch("/login", {
method: "POST",
headers: {
"Content-Type" : "application/json", //사용자 -> 서버에 로그인한 정보가 일치하는게 있는지 확인
"Accept" : "application/json"}, // 서버 -> 사용자에게 사용자가 작성한 정보가 존재하는지에 대한 여부 전달
body : JSON.stringify({id : id, pw : pw}) //본문으로 id, pw 작성된 내용 전달
})
.then(res => res.json())
.then(map => {
console.log(map);
//로그인 실패시
if(map.loginMember === null){
alert('아이디 또는 비밀번호가 일치하지 않습니다.');
return;
}
//로그인 성공시
setLoginMember(map.loginMember);
//App.js에 로그인 성공한 정보가 올라감. App.js는 로그인 정보를 다른 js에 전달
//id, pw값 모두 지우기
setId('');
setPw('');
})
}
return(
<div className="login-container">
<table>
<tbody>
<tr>
<th>ID</th>
<td>
<input type="text" onChange={e => setId(e.target.value)} value={id}/>
</td>
</tr>
<tr>
<th>PW</th>
<td>
<input type="password" onChange={e => setPw(e.target.value)} value={pw}/>
</td>
<td>
<button onClick={loginBtn}>로그인</button>
</td>
</tr>
</tbody>
</table>
</div>
)
}
export default Login;
LoginContext.js
import React,{createContext} from "react";
const LoginContext = createContext();
export default LoginContext;
SignUp.js
import React, {useState} from "react";
const Signup = () => {
const [id, setId] = useState('');
const [pw, setPw] = useState('');
const [pwCheck, setPwCheck] = useState('');
const [name, setName] = useState('');
const [result, setResult] = useState('');
//아이디 중복검사
const [idValidation, setIdValidation] = useState(false);
//false = 사용 불가, true = 사용 가능
//중복검사 이벤트 핸들러
const idDup = (eventId) => {
//eventId = 현재 입력하는 이벤트가 발생한 id
setId(eventId);
//4글자 미만이면 중복검사 x
//입력 받은 아이디의 공백을 제거하고 길이가 4보다 작다면
//trim() : 양 옆의 공백 제거
if(eventId.trim().length < 4){
setIdValidation(false);
return;
}
//DB에 중복되는 아이디가 있는지 비동기로 아이디 중복검사 수행
//axios나 fetch 사용
fetch("/idCheck?id=" + eventId) //SpringBoot Controller와 연결할 Mapping url
.then(res => res.text())
.then(result => {
//중복이 아닐 때 true 맞다면 false
//(Number(result) === 0) -> SpringBoot에서 중복이 아니면 0, 중복이면 1 이상의 값 전달
//꼭 숫자값이 아니라 글자여도 상관없음
if(Number(result) === 0){
setIdValidation(true);
}
else{
setIdValidation(false);
}
})
}
const signUpBtn = () => {
//아이디 유효하지 않으면 가입 x
if(!idValidation){
alert("유효한 아이디가 아닙니다.");
return;
}
if(pw !== pwCheck){
alert('비밀번호와 비밀번호 확인이 일치하지 않습니다.');
return;
}
//비밀번호, 비밀번호 확인이 일치하는지 확인
//회원가입 비동기 요청
const inputValues = {}; //초기에 들어온 값이 없으니 빈 공간으로 설정
inputValues.id = id; //id 값이 들어오면 inputValues에 id 값을 작성
inputValues.pw = pw; //pw 값이 들어오면 inputValues에 pw 값을 작성
inputValues.name =name;
//input에 id값으로 ksh를 작성하고 pw로 ksh1234를 작성시
//inputValues = {ksh, ksh1234}; 가 됨
fetch("/signup", {
method:"POST", //스프링부트 컨트롤러에 @PostMapping("/signup")에 전달
//headers : 메일로 치면 메일 주소,제목 처럼 초기에 어떤 것을 보내는지 설정
headers: {"Content-Type" : "application/json"}, //<form> 태그에 해당 내용들이 기본값으로 들어가 있음
//body : 내용 본문 작성
body : JSON.stringify(inputValues) //사용자가 작성한 모든 값들을 보내기
})
.then(res => res.text())
.then(result => {
if(Number(result) > 0){ //결과가 1 이상이면 회원가입 완료처리
setResult('회원 가입 성공');
//input 값들 모두 초기화
setId('');
setPw('');
setPwCheck('');
setName('');
}
else{
setResult('회원 가입 실패');
}
})
}
return(
<div className="signup-container">
{/* label의 htmlFor와 input의 id를 생략하고 싶다면 input을 라벨 안에 작성해주면 됨 */}
<label>
ID :
<input type="text" onChange={e => idDup(e.target.value)}
value={id}
className={idValidation ? '' : 'id-err'}
/>
</label>
<label>
PW :
<input type="password" onChange={e => setPw(e.target.value)}
value={pw}
/>
</label>
<label>
PW CHECK :
<input type="password" onChange={e => setPwCheck(e.target.value)}
value={pwCheck}
/>
</label>
<label>
NAME :
<input type="text" onChange={e => setName(e.target.value)}
value={name}
/>
</label>
<button onClick={signUpBtn}>가입하기</button>
<hr/>
{/* 회원가입 결과 출력 */}
<h3>{result}</h3>
</div>
)
}
export default Signup;
** headers: {"Content-Type" : "application/json"} => <form> 태그에 해당 내용들이 기본값으로 들어가 있음
- Content-Type : 데이터 전달 시 이미지인지, 파일인지 등 정보를 전달
- application/json :
- application : 코딩하는 폴더 자체. 폴더 1개 = 어플리캐이션 1개
- json : 사용자나 개발자가 작성한 값들을 key-value의 형태로 1개 이상 주고 받을 수 있는 형태
App.js
import React, {useState} from 'react';
import LoginContext from './components/LoginContext';
import Signup from './components/Signup';
import Login from './components/Login';
import './App.css';
// App.js는 제일 상위 컴포넌트(객체)
function App() {
//회원 가입 창 보이기 / 숨기기
const [signUpView, setSignUpView] = useState(false);
//로그인한 회원 정보 저장
const [loginMember, setLoginMember] = useState(null);
return (
<LoginContext.Provider value={{loginMember, setLoginMember}}>
<button onClick={() => {setSignUpView(!signUpView)}}>
{signUpView ? '회원 가입 닫기' : '회원 가입 열기'}
</button>
{/* 회원 가입 화면 */}
<div className='"signup-wrapper'>
{/* signUpView가 true 일 경우에만 실행되는 공간 = 눈에 보여짐 */}
{/* 조건식 && (true일 경우 실행) */}
{signUpView === true && (<Signup/>)}
</div>
<h1>Todo List</h1>
{/* 로그인을 해야 TodoList 보이도록 */}
<Login/>
</LoginContext.Provider>
);
}
export default App;
** 로그인을 한 다음에 로그인한 정보를 모든 창에 띄워주기
=> App.js에서 div태그 대신에 LoginContext 태그로 return을 감싸주면 LoginContext 태그 안의 모든 태그에서는 로그인/로그아웃한 정보가 공유됨
** <LoginContext.Provider value={{loginMember, setLoginMember}}>
- value = {} -> 하나의 값만 작성
- value = {{}} -> 2개 이상의 값을 작성
- loginMember = 처음 로그인 안된 초기값을 가지고 있음
- setLoginMember = 로그인 후 로그인한 정보를 가지고 있음
'React' 카테고리의 다른 글
React - SpringBoot 연결하기 (회원가입+todo리스트 만들기) 3 (0) | 2024.07.16 |
---|---|
React - SpringBoot 연결하기 (회원가입+todo리스트 만들기) 2 (0) | 2024.07.15 |
프로필 사진 넣기 (0) | 2024.07.12 |
PagiNation 2 (0) | 2024.07.12 |
PagiNation 1 (0) | 2024.07.12 |