What I Learnd/TIL

TIL - TypeScript로 방명록 남기기 페이지 만들기

키싸 2023. 8. 3. 23:49

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로 상태를 설정하는 함수