📦 설치한 패키지
- react, react-router-dom
- axios
📂 프로젝트 구조
📦 src
├── 📂 apis : API 호출과 관련된 함수 모음
├── 📂 components : Page에서 사용되는 컴포넌트 모음
├── 📂 helper : 재사용되는 함수 모음
├── 📂 hooks : Custom Hook
├── 📂 pages : 페이지 컴포넌트
└── 📂 styles : CSS 모음
1. 이메일, 비밀번호 유효성 검사
이메일 조건: @ 포함
비밀번호 조건: 8자 이상
로그인과 회원가입 간에 변경되는 데이터를 받아 주어진 조건에 맞게 유효성을 검사하는 함수를 만들어 검사한다.
// helper/validationCheck.js
export const checkEmail = (email) => {
return email.indexOf("@") === -1 ? "fail" : "success";
};
export const checkPassword = (password) => {
return password.length < 8 ? "fail" : "success";
};
결과에 따라 fail
과 success
를 반환하고 유효성 검사를 통과 여부에 따라 button
의 활성화 여부가 변경된다.
// /pages/Login.jsx
<button
type="submit"
className="member-wrapper-button"
disabled={
checkEmail(email) === "success" &&
checkPassword(password) === "success"
? ""
: "disabled"
}
data-testid="signin-button"
>
로그인
</button>
2. 회원가입 완료 시 /signin
이동
회원가입 API 호출 후, 응답의 상태 코드가 200인 경우에 로그인 페이지로 이동한다. (회원가입이 완료되지 못하고 에러가 발생하는 경우, 사용자에게 에러 메시지를 alert
)
// /pages/Signup.jsx
const signupSubmitHandler = async (event) => {
event.preventDefault();
const userInfo = { email, password };
try {
const response = await signup_API(userInfo);
if (response.status === 201) {
routeTo("/signin");
}
} catch (error) {
const { response } = error;
alert(response.data?.message);
}
};
routeTo
함수는 페이지를 이동하는 함수
3. 로그인 완료 시 /todo
이동
로그인 버튼을 클릭하면 아래의 loginSubmitHandler
함수가 실행한다.
함수가 실행되면 로그인 API 호출(signin_API
) 후, 응답의 상태 코드가 200인 경우에 발급받은 토큰을 localStorage
에 저장하고 /todo
로 이동된다.
// /pages/Login.jsx
const loginSubmitHandler = async (event) => {
event.preventDefault();
const userInfo = { email, password };
try {
const response = await signin_API(userInfo);
if (response.status === 200) {
setLocalStorage(response.data);
routeTo("/todo");
}
} catch (error) {
console.log(error);
}
};
setLocalStorage
함수는localStorage
에 토큰을 저장
4. 로그인 여부에 따른 리다이렉트 구현
각 페이지에서 useEffect를 사용하여 localStorage에 토큰의 여부에 따라 리다이렉트 된다.
이 방법은 별로 좋지 않은 방법이라고 생각된다. 페이지마다 코드를 반복하지 않고 구현할 수 있는 방법을 생각하면 좋을 것 같다.
// /pages/Login.jsx
useEffect(() => {
if (!!getLocalStorage("token")) {
routeTo("/todo");
}
}, []);
// /pages/Todo.jsx
useEffect(() => {
if (!getLocalStorage("token")) {
return routeTo("/signin");
}
....
,[]);
5. /todo
에서 TODO 리스트 목록 표시
각각의 TODO를 나타내는 TodoItems
컴포넌트를 분리하여 만들었다.
useEffect
를 사용하여 /todo
페이지가 처음 마운트 되었을 때, TODO 리스트를 불러오는 getTodo_API
함수를 실행한다. 응답 상태코드가 200인 경우, 서버로부터 받은 리스트를 상태 값으로 저장한다.
// /pages/Todo.jsx
useEffect(() => {
if (!getLocalStorage("token")) {
return routeTo("/signin");
}
const getMyTodo = async () => {
try {
const response = await getTodo_API();
if (response.status === 200) {
setTodoLit(response.data);
}
} catch (error) {
console.log(error);
}
};
getMyTodo();
}, []);
6. TODO 추가
작성한 TODO를 추가하는 버튼을 클릭하면 onSubmitHandler
함수를 실행한다.
함수가 실행되면 작성된 TODO를 객체로 담아서 createTodo_API
함수를 실행하고, API 호출 후에 응답 상태코드가 201인 경우, 이전에 저장되어 있던 리스트 상태값의 가장 아래에 새로 저장된 TODO를 추가한 뒤 입력 창을 비워준다.
// /pages/Todo.jsx
const onSubmitHandler = async (event) => {
event.preventDefault();
const newTodo = {
todo: writeTodo,
};
try {
const response = await createTodo_API(newTodo);
if (response.status === 201) {
setTodoLit([...todoList, response.data]);
setWriteTodo("");
}
} catch (error) {
console.log(error);
}
};
7. chekbox로 완료 여부 수정
onCompletHandler
함수는 체크박스 변경과 update API(updateTodo_API
)를 호출한다.
// /components/TodoItems.jsx
const onCompletHandler = async () => {
const body = { todo: chageTodo, isCompleted: !isChecked };
try {
const response = await updateTodo_API(id, body);
if (response.status === 200) {
setIsChecked((prev) => !prev);
}
} catch (error) {
console.log(error);
}
};
8. TODO 수정 및 삭제 버튼
// /components/TodoItems.jsx
<li>
<label>
<input
className="m-r todo-todoList-check"
type="checkbox"
onChange={onCompletHandler}
checked={isChecked ? "checked" : ""}
/>
<span>{chageTodo}</span>
</label>
<div>
<button
className="todo-todoList-button"
data-testid="modify-button"
onClick={onModifyHandler}
>
수정
</button>
<button
className="m-l todo-todoList-button"
data-testid="delete-button"
onClick={() => onDeleteHandler(id)}
>
삭제
</button>
</div>
</li>;
9. TODO 삭제
삭제 버튼을 클릭하면 onDeleteHandler
함수가 실행된다. 함수가 실행되면 해당 아이템을 지우는 API(deleteTodo_API
)를 호출하고, 응답 상태코드가 204인 경우, 리스트를 담고 있는 상태 값(배열)을 filter
매서드를 사용하여 해당 TODO 아이템을 제거한다.
// /pages/Todo.jsx
const onDeleteHandler = useCallback(async (id) => {
try {
const response = await deleteTodo_API(id);
if (response.status === 204) {
setTodoLit((prev) => [...prev].filter((todo) => todo.id !== id));
}
} catch (error) {
console.log(error);
}
}, []);
10. TODO 수정
isModify
상태 값에 따라 수정모드가 활성화 여부가 변경된다.
TODO를 수정한 후에 수정 버튼을 클릭하면 onSubmitHandler
함수가 실행되어 수정 API(updateTodo_API
)를 호출한다. 호출 결과 응답 상태코드가 200인 경우, isModify
상태 값을 변경하여 수정 모드를 비활성화 한다.
// /components/TodoItems.jsx
const onModifyHandler = () => {
setIsModify((prev) => !prev);
};
const onSubmitHandler = async () => {
const body = { todo: chageTodo, isCompleted: isChecked };
try {
const response = await updateTodo_API(id, body);
if (response.status === 200) {
onModifyHandler();
}
} catch (error) {
console.log(error);
}
};
https://github.com/lIIIlIIIlIIIl/wanted-pre-onboarding-frontend
GitHub - lIIIlIIIlIIIl/wanted-pre-onboarding-frontend
Contribute to lIIIlIIIlIIIl/wanted-pre-onboarding-frontend development by creating an account on GitHub.
github.com
'개발이야기 > 원티드' 카테고리의 다른 글
[프리온보딩 프론트엔드 인턴십] 1주차 (0) | 2023.07.03 |
---|