TIL - TypeScript로 방명록 남기기 페이지 만들기
yarn create react-app <folder-name> --template typescript
import React, { useEffect, useState } from "react";
import styled from "styled-components";
import { Button, Input, message } from "antd";
import axios from "axios";
ㄴ 프로젝트 생성하고 필요한 모듈 설치. axios로 json server의 데이터 받아올 예정
const Main: React.FC<any> = () => {
ㄴ 메인 컴포넌트를 정의하고 any 타입의 props를 받아온다.
const [data, setData] = useState([]);
const [contents, setContents] = useState<string>("");
ㄴ data와 contents라는 두개의 상태를 선언한다. data는 남길 방명록의 메세지를 데이터 배열 상태를 보여줄거고, contents는 입력한 메세지의 내용을 저장한다.
const fetchData = () => {
// ...
};
ㄴ fetchData 함수를 선언하고 서버로부터 데이터를 가져와보자
const fetchData = async () => {
// TODO: 데이터베이스에서 boards 리스트 가져오기
try {
const response = await axios.get(`http://localhost:4000/boards`);
// TODO: 가져온 결과 배열을 data state에 set 하기
setData(response.data);
} catch (error) {
alert("일시적인 오류가 발생하였습니다. 고객센터로 연락주세요.");
return false;
}
};
ㄴ 데이터와 통신할 때에는 반드시 try catch문 사용해서 통신한다!
ㄴ4000번 포트로 db.json 데이터 보여주고있으며, axios.get으로 boards 안에 있는 데이터를 불러온다
ㄴ불러온 데이터는 setData로 보여주고, 연결에 문제가 있을 시, catch alert
useEffect(() => {
fetchData();
}, []);
ㄴuseEffect로 불러온 데이터를 동작시키되 최초 마운트시에만 동작하도록 뒤에 빈 배열을 넣어준다 잊지말자
const loggedInUserEmail = localStorage.getItem("email");
ㄴ 로그인 되어있는 유저의 이메일로 방명록을 남길 때에 이메일 정보를 함께 저장, 이후 해당 유저가 작성한 글에만 삭제버튼을 노출시킬 예정이다
const handleBoardSubmit = (e: any) => {
// TODO: 자동 새로고침 방지
e.preventDefault();
try {
axios.post("http://localhost:4000/boards", {
email: loggedInUserEmail,
contents: contents,
isDeleted: false,
});
setData(data);
alert("작성이 완료되었습니다.");
// TODO: 처리완료 후, reload를 이용하여 새로고침
window.location.reload();
} catch (error) {
alert("일시적인 오류가 발생하였습니다. 고객센터로 연락주세요.");
}
};
ㄴ 방명록 제출 버튼 핸들러로, any 타입의 정보를 제출한다.
ㄴ 위에서 언급했듯이 loggedInUserEmail로 유저의 이메일 정보를 함께 post 한다.
const handleInputChange = (e: any) => {
setContents(e.target.value);
};
ㄴ 메세지를 등록하는 함수
return (
<MainWrapper>
<h1>메인 리스트 페이지</h1>
<StyledForm onSubmit={handleBoardSubmit}>
<StyledInput
placeholder="방명록을 입력해주세요."
value={contents}
onChange={handleInputChange}
/>
<Button>작성</Button>
</StyledForm>
<ListWrapper>
{data.map((item: any, index) => (
<ListItem key={item.id}>
<span>
{index + 1}. {item.contents}
</span>
{/* // TODO: 로그인 한 user의 이메일과 일치하는 경우에만 삭제버튼 보이게!*/}
{item.email === loggedInUserEmail && (
<Button onClick={() => handleDelete(item.id)}>삭제</Button>
)}
</ListItem>
))}
</ListWrapper>
</MainWrapper>
);
};
ㄴ JSX 코드로 페이지를 렌더링
ㄴ map으로 any 타입의 item을 뿌려주는데, 데이터의 이메일과 유저의 이메일이 동일할 경우에만 삭제버튼을 보여준다.
const handleDelete = async (id: string) => {
try {
await axios.delete(`http://localhost:4000/boards/${id}`);
// 삭제 성공 다시 state 세팅
setData(data.filter((item: any) => item.id !== id));
alert("삭제되었습니다.");
} catch (error) {
alert("일시적인 오류가 발생하였습니다. 고객센터로 연락주세요.");
}
};
ㄴaxios.delete으로 아이디 값이 동일한 데이터를 삭제 하고 setData로 상태를 설정하는 함수