Login, SignUp 페이지 단위의 컴포넌트를 만들고 input과, button을 component로 만들어서 가져오고 싶었다.
input.jsx
function Input({ ...props }) {
return (
<Wrapper>
<InputText {...props}></InputText>
</Wrapper>
)
}
export default Input;
Login.jsx
function Login() {
return (
<Wrapper>
<Container>
<Title>Welcome</Title>
<form onSubmit={onSubmit}>
<Input name="email" placeholder="이메일" />
<Input name="password" type="password" placeholder="비밀번호" />
<Button type="submit">Sign In</Button>
</form>
</Container>
<Link to='/signup'>
<Footer>계정이 없으신가요?</Footer>
</Link>
</Wrapper>
)
}
export default Login;
button은 children을 이용하였는데
Button.jsx
function Button({children, ...props}) {
return (
<ButtonStyled {...props}>{children}</ButtonStyled>
)
}
export default Button;
function Login() {
const navigate = useNavigate();
const onSubmit = (e) => {
e.preventDefault();
return (
<Wrapper>
<Container>
<Title>Welcome</Title>
<form onSubmit={onSubmit}>
<Input name="email" placeholder="이메일" />
<Input name="password" type="password" placeholder="비밀번호" />
<Button type="submit">Sign In</Button>
</form>
</Container>
<Link to='/signup'>
<Footer>계정이 없으신가요?</Footer>
</Link>
</Wrapper>
)
}
export default Login;
function Login() {
const navigate = useNavigate();
const onSubmit = (e) => {
e.preventDefault();
if (!e.target.email.value) {
alert("이메일을 입력하세요");
e.target.email.focus()
return
}
if (!e.target.password.value) {
alert("비밀번호를 입력하세요");
e.target.password.focus()
return
}
console.log(e.target.email.value);
}
return (
<Wrapper>
<Container>
<Title>Welcome</Title>
<form onSubmit={onSubmit}>
<Input name="email" placeholder="이메일" />
<Input name="password" type="password" placeholder="비밀번호" />
<Button type="submit">Sign In</Button>
</form>
</Container>
<Link to='/signup'>
<Footer>계정이 없으신가요?</Footer>
</Link>
</Wrapper>
)
}
export default Login;
function SignUp() {
signUp({
email: e.target.email.value,
password: e.target.password.value,
name: e.target.name.value,
gender: e.target.gender.value
})
const signUp = async({email, password, name, gender}) => {
try{
await axios.post('/user/signup', {
email,
password,
name,
gender
})
alert('회원가입이 완료되었습니다');
} catch (err) {
console.log(err)
}
}
return (
<Wrapper>
<Container>
<Title>Welcome</Title>
<form onSubmit={onSubmit}>
<Input name="email" placeholder="이메일" />
<Input name="password" type="password" placeholder="비밀번호" />
<Input name="name"placeholder="이름" />
<Input name="gender" placeholder="성별" />
<Button type="submit">Sign Up</Button>
</form>
</Container>
<Link to='/'>
<Footer>로그인으로</Footer>
</Link>
</Wrapper>
)
}
export default SignUp;
function SignUp() {
const [toggle, setToggle] = useState(false);
const onSubmit = (e) => {
e.preventDefault();
// 유효성 검사
if (!e.target.email.value) {
alert("이메일을 입력하세요");
e.target.email.focus()
return
}
if (!e.target.password.value) {
alert("비밀번호를 입력하세요");
e.target.password.focus()
return
}
if (!e.target.name.value) {
alert("이름을 입력하세요");
e.target.name.focus()
return
}
if (!e.target.gender.value) {
alert("성별을 입력하세요");
e.target.gender.focus()
return
}
// console.log(e.target.email.value)
signUp({
email: e.target.email.value,
password: e.target.password.value,
name: e.target.name.value,
gender: e.target.gender.value
})
}
const signUp = async({email, password, name, gender}) => {
try{
await axios.post('/user/signup', {
email,
password,
name,
gender
})
alert('회원가입이 완료되었습니다');
setToggle(true)
} catch (err) {
console.log(err)
}
}
return (
<Wrapper>
<Container>
<Title>Welcome</Title>
<form onSubmit={onSubmit}>
<Input name="email" placeholder="이메일" />
<Input name="password" type="password" placeholder="비밀번호" />
<Input name="name" placeholder="이름" />
<Input name="gender" placeholder="성별" />
<Button type="submit" disabled={toggle}>Sign Up</Button>
</form>
</Container>
<Link to='/'>
<Footer>로그인으로</Footer>
</Link>
</Wrapper>
)
}
export default SignUp;
const [toggle, setToggle] = useState(false);
→ boolen 타입이니까 초기값을 우리는 true가 아닌 false로 준다. → disabled={toggle}
: toggle을 객체로 담아주고 → setToggle(true)
: 회원가입이 성공 했을 때 버튼이 비활성화가 되어야 하니까 alert창 띄어주는 코드 다음에 코드를 작성해준다.로그인도 회원 가입처럼 유효성 검사까지 한 후 axios 요청을 보내야 한다.
function Login() {
const navigate = useNavigate();
const onSubmit = (e) => {
e.preventDefault();
if (!e.target.email.value) {
alert("이메일을 입력하세요");
e.target.email.focus()
return
}
if (!e.target.password.value) {
alert("비밀번호를 입력하세요");
e.target.password.focus()
return
}
console.log(e.target.email.value);
signUp({
email: e.target.email.value,
password: e.target.password.value,
})
}
const signUp = async({email, password}) => {
try{
const response = await axios.post('/user/signin', {
email,
password,
})
alert('로그인이 완료되었습니다');
console.log(response.data.data.token)
localStorage.setItem('token', response.data.data.token)
navigate("/main");
} catch (err) {
console.log(err)
alert('로그인에 실패했습니다');
}
}
export default Login;
setItem
으로 localStorage에 저장한다.App.js에서 우리는 토큰이 있을 때와 없을 때 페이지 리다이렉트를 구현 해야한다.
useEffect(function () {
// localstorage에 저장되어 있는 토큰 값이 있는지 없는지 검사
const token = localStorage.getItem("token");
console.log(location);
const isCurrentRootPath = location.pathname === "/"; // isCurrentRootPath 로그인 페이지
if (!token) {
// token이 없을 경우
if (!isCurrentRootPath) {
// 로그인 페이지가 아닐 때
navigate("/"); // 로그인 페이지로 이동
}
} else {
// token이 있을 경우 (로그인 기록이 있을 때) -> useProperty 가져와야함 -> 저장 방법 (recoil)
// 토큰이 만료되었을 때 오류 처리
if (isCurrentRootPath) {
// 로그인 페이지일 때
navigate("/main"); // main 페이지로 이동
}
}
}, []);
에러를 확인할 때 console에서 하나하나 찾기 귀찮아서 middleware을 만들어서 요청을 보냈다.
import axios from "axios";
const middleware = axios.create({
baseURL: "http://",
});
middleware.interceptors.request.use(
function (request) {
return request;
},
function (error) {
return error;
}
);
middleware.interceptors.response.use(
function (response) {
return response;
},
function (error) {
if (!error.response.data) {
throw new Error("알 수 없는 오류");
}
throw error.response.data;
}
);
export default middleware;
import axios from "axios";
const middleware = axios.create({
baseURL: "http://",
});
export const setHeader = token => {
// 1. 헤더에 token을 넣어줌
middleware.defaults.headers.common["Authorization"] = `Bearer ${token}`;
};
middleware.interceptors.request.use(
function (request) {
return request;
},
function (error) {
return error;
}
);
middleware.interceptors.response.use(
function (response) {
return response;
},
function (error) {
if (!error.response.data) {
throw new Error("알 수 없는 오류");
}
throw error.response.data;
}
);
export default middleware;
axios를 사용할 때마다 자동으로 header에 Authorization이 적용될 수 있도록 한다
useEffect(function () {
// localstorage에 저장되어 있는 토큰 값이 있는지 없는지 검사
const token = localStorage.getItem("token");
console.log(location);
const isCurrentRootPath = location.pathname === "/"; // isCurrentRootPath 로그인 페이지
if (!token) {
// token이 없을 경우
if (!isCurrentRootPath) {
// 로그인 페이지가 아닐 때
navigate("/"); // 로그인 페이지로 이동
}
} else {
// token이 있을 경우 (로그인 기록이 있을 때) -> useProperty 가져와야함 -> 저장 방법 (recoil)
// 토큰이 만료되었을 때 오류 처리
if (isCurrentRootPath) {
setHeader(token);
// 로그인 페이지일 때
navigate("/main"); // main 페이지로 이동
}
}
}, []);
async function getProperty(isCurrentRootPath) {
try {
const response = await axios.get("/user/property");
setUser(response.data.data.user);
if (isCurrentRootPath) {
// 로그인 페이지일 때
navigate("/main"); // main 페이지로 이동
}
} catch (err) {
console.log(err);
navigate("/"); // 로그인 페이지로 넘어감 -> 없을 때
}
}
useEffect(function () {
// localstorage에 저장되어 있는 토큰 값이 있는지 없는지 검사
const token = localStorage.getItem("token");
console.log(location);
const isCurrentRootPath = location.pathname === "/"; // isCurrentRootPath 로그인 페이지
if (!token) {
// token이 없을 경우
if (!isCurrentRootPath) {
// 로그인 페이지가 아닐 때
navigate("/"); // 로그인 페이지로 이동
}
} else {
// token이 있을 경우 (로그인 기록이 있을 때) -> useProperty 가져와야함 -> 저장 방법 (recoil)
// 토큰이 만료되었을 때 오류 처리
if (isCurrentRootPath) {
setHeader(token);
getProperty(isCurrentRootPath);
}
}
}, []);
→ store 폴더에 user.js 파일을 만들고 npm recoil → atom 코드 작성 → index.js에 RecoilRoot 해주기(?)
import { atom } from "recoil";
export const usePropertyState = atom({
// userProperty를 중앙 관리함
key: "usePropertyState",
default: null,
});
import React, { useEffect, useState } from 'react';
import axios from '../../api/config';
import { usePropertyState } from '../../store/user';
import { useRecoilState } from 'recoil';
function Main() {
const [board, setBoard] = useState([]);
const [userProperty, setUserProperty] = useRecoilState(usePropertyState)
useEffect(() => {
async function getData(){ // board를 가져오는 함수
try {
const response = await axios.get('/board', { params: { page:1, size:30 }}) // object에서 params 값을 추가해서 요청, page1
console.log(response)
} catch (err) {
console.log(err);
}
}
if(userProperty) { // userProperty가 있을 경우
getData(); // getData 실행
}
}, [userProperty])
return (
<div>Main</div>
)
}
export default Main;
import axios from "axios";
const middleware = axios.create({
baseURL: "http://",
});
export const setHeader = token => {
// 1. 헤더에 token을 넣어줌
middleware.defaults.headers.common["Authorization"] = `Bearer ${token}`;
};
export const removeHeader = () => {
delete middleware.defaults.headers.common["Authorization"];
};
middleware.interceptors.request.use(
function (request) {
return request;
},
function (error) {
return error;
}
);
middleware.interceptors.response.use(
function (response) {
return response;
},
function (error) {
if (!error.response.data) {
throw new Error("알 수 없는 오류");
}
throw error.response.data;
}
);
export default middleware;
async function getProperty(isCurrentRootPath) {
try {
const response = await axios.get("/user/property");
setUser(response.data.data.user);
if (isCurrentRootPath) {
// 로그인 페이지일 때
navigate("/main"); // main 페이지로 이동
}
} catch (err) {
console.log(err);
alert("로그인 정보가 만료되었습니다"); // 토큰이 만료되면 alert창 띄워주고
navigate("/"); // 로그인 페이지로 넘어감
localStorage.removeItem("token"); // token를 localstorage에서 지워줌
removeHeader(); // axios header에서 지워줌
}
}