Home 미니 블로그 만들기 - 05
Post
X

미니 블로그 만들기 - 05

Axios 설치

서버에 데이터를 요청하기 위해서는 HTTP 통신을 해야합니다.

React에는 HTTP 통신을 위한 내장 클래스가 존재하지 않기 떄문에 XMLRequest, fetch, axios 등을 사용하여 ajax를 구현합니다.

이번엔 axios를 사용해서 서버에 데이터를 요청해보겠습니다.

  • 설치

    1
    
    npm i axios
    

BoardPage 수정하기

기존에는 data.json 파일 import해서 글 데이터를 PostList 컴포넌트에 념겨줬습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// BoardPage.jsx
import React from "react";
import { styled } from "@mui/material/styles";
import { useNavigate } from "react-router-dom";
import BasicButton from "../ui/BasicButton";
import PostList from "../list/PostList";
import data from "../../data.json";

const BtnWrapper = styled.div`
  margin-left: auto;
`;

const BoardPage = () => {
  const navigate = useNavigate();

  return (
    <>
      <BtnWrapper>
        <BasicButton
          title={"글 작성하기"}
          onClickItem={() => navigate("/post-write")}
        ></BasicButton>
      </BtnWrapper>

      <PostList
        posts={data}
        onClickItem={(item) => {
          navigate(`/post/${item.id}`);
        }}
      ></PostList>
    </>
  );
};

export default BoardPage;

이번에는 axios로 서버에 글 데이터를 요청해보겠습니다.

참고 글 : Axios, Hook

  • 수정할 내용

    • data.json 대신 axios로 서버에서 데이터 얻기
    • 가져온 데이터 State로 관리
    • 컴포넌트가 Mount 될 때만 데이터 가져오도록 useEffect 사용
    • await / async 문 사용
    • try / catch 문 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import React, { useEffect, useState } from "react";
import { styled } from "@mui/material/styles";
import { useNavigate } from "react-router-dom";
import BasicButton from "../ui/BasicButton";
import PostList from "../list/PostList";
import axios from "axios"; // data.json 대신 axios 사용

const BtnWrapper = styled("div")`
  margin-left: auto;
`;

const BoardPage = () => {
  const navigate = useNavigate();
  let [data, setData] = useState([]); // 가져올 데이터 담을 변수

  useEffect(() => {
    let getPosts = async () => {
      try {
        let res = await axios.get("/board/post");

        return res.data;
      } catch (err) {
        console.log(err);
      }
    }; // try / catch 문으로 에러 처리를 하며 axios를 이용해 서버에서 데이터를 가져옵니다.

    getPosts().then((res) => setData(res));
    // 가져온 데이터를 state로 관리합니다.
  }, []); // 빈 배열로 컴포넌트가 Mount 될 때만 작동합니다.

  return (
    <>
      <BtnWrapper>
        <BasicButton
          title={"글 작성하기"}
          onClickItem={() => navigate("/board/write")}
        ></BasicButton>
      </BtnWrapper>

      <PostList
        posts={data}
        onClickItem={(item) => {
          navigate(`/board/${item.post_id}`);
        }}
      ></PostList>
    </>
  );
};

export default BoardPage;

PostViewPage 수정하기

위와 마찬가지로 기존에는 data.json 파일 import해서 특정 id 값의 글 데이터를 가져왔습니다.

  • 수정할 내용
    • axios로 특정 post_id 값의 글 데이터를 가져옵니다.
    • axios롤 댓글 데이터를 가져옵니다.
    • 댓글 추가 기능 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// PostViewPage.jsx
import React, { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { styled } from "@mui/material/styles";
import CommentList from "../list/CommentList";
import TextInput from "../ui/TextInput";
import BasicButton from "../ui/BasicButton";
import axios from "axios";

const BtnWrapper = styled("div")`
  margin-left: auto;
`;

const PostContainer = styled("div")`
  padding: 1rem;
  border: 1px solid grey;
  border-radius: 8px;
`;

const TitleText = styled("p")`
  margin: 0;
  font-size: 1.5rem;
  font-weight: 600;
`;

const ContentText = styled("p")`
  font-size: 1rem;
  line-height: 2rem;
  white-space: pre-wrap;
`;

const CommentLabel = styled("p")`
  font-size: 1rem;
  font-weight: 500;
`;

const PostViewPage = () => {
  const navigate = useNavigate();
  const [data, setData] = useState([]);
  const [post, setPost] = useState([]);
  const [comment, setComment] = useState("");

  const { postId } = useParams();

  useEffect(() => {
    const getPostById = async () => {
      try {
        let res = await axios.get(`/board/post/${postId}`);

        return res.data;
      } catch (err) {
        console.log(err);
      }
    };

    getPostById().then((res) => setPost(res));

    let getComments = async () => {
      try {
        let res = await axios.get(`/board/comment/${postId}`);

        return res.data;
      } catch (err) {
        console.log(err);
      }
    };

    getComments().then((res) => setData(res));
  }, [postId]);

  const addComment = async () => {
    try {
      let res = await axios.post(`/board/comment/${post.post_id}`, {
        content: comment,
      });

      return res.data;
    } catch (err) {
      console.log(err);
    }
  };

  return (
    <>
      <BtnWrapper>
        <BasicButton
          title={"뒤로 가기"}
          onClickItem={() => {
            navigate("/board");
          }}
        ></BasicButton>
      </BtnWrapper>

      <PostContainer>
        <TitleText>{post.title}</TitleText>
        <ContentText>{post.content}</ContentText>
      </PostContainer>

      <CommentLabel>댓글</CommentLabel>
      <CommentList comments={data}></CommentList>

      <TextInput
        rows={5}
        placeholder="댓글 내용"
        value={comment}
        onChange={(event) => {
          setComment(event.target.value);
        }}
      ></TextInput>

      <BtnWrapper>
        <BasicButton
          title={"댓글 작성하기"}
          onClickItem={() => {
            addComment();

            window.location.reload();
          }}
        ></BasicButton>
      </BtnWrapper>
    </>
  );
};

export default PostViewPage;

BoardPage에서 PostViewPage로 글 데이터를 props로 넘겨줄 수 없을까?

BoardPage에서 글을 클릭하면 Navigate가 작동해 postViewPage로 넘어옵니다.

이 때, Navigate 함수에 두 번쨰 인자로 state를 넘겨주면 이동할 페이지에서 state 값을 활용할 수 있습니다.

즉, 따로 서버에 특정 글 데이터를 요청하지 않고 BoardPage에서 얻은 데이터를 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// BoardPage.jsx
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import PostList from "../list/PostList";
import axios from "axios";

const BoardPage = () => {
  const navigate = useNavigate();
  let [data, setData] = useState([]);

  useEffect(() => {
    let getPosts = async () => {
      try {
        let res = await axios.get("/board/post");

        return res.data;
      } catch (err) {
        console.log(err);
      }
    };

    getPosts().then((res) => setData(res));
  }, []);

  return (
    <>
      <PostList
        posts={data}
        onClickItem={(item) => {
          navigate(`/board/${item.post_id}`, { state: { post: item } });
          // navigate 함수의 두 번쨰 인자로 state를 객체로 넘겨줍니다.
        }}
      ></PostList>
    </>
  );
};

export default BoardPage;

useLocation 에서 state의 값으로 넘겨받을 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// PostViewPage.jsx
import React from "react";
import { useNavigate, useLocation } from "react-router-dom";

const PostViewPage = () => {
  const navigate = useNavigate();
  const [data, setData] = useState([]);
  const [comment, setComment] = useState("");

  const location = useLocation();

  const post = location.state.post;

  return (
    <>
      <PostContainer>
        <TitleText>{post.title}</TitleText>
        <ContentText>{post.content}</ContentText>
      </PostContainer>
    </>
  );
};

export default PostViewPage;

하지만, 이런 경우 BoardPage에서 글을 클릭하여 페이지가 이동했을 때는 작동하지만 URL을 입력할 경우에는 작동하지않습니다.


PostWritePage 수정하기

비슷한 방법으로 글 작성 페이지도 수정해주곘습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// PostWritePage.jsx
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { styled } from "@mui/material/styles";
import BasicButton from "../ui/BasicButton";
import TextInput from "../ui/TextInput";
import axios from "axios";

const BtnWrapper = styled("div")`
  margin-left: auto;
`;

const PostWritePage = () => {
  const navigate = useNavigate();

  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");

  const addPost = async () => {
    try {
      let res = await axios.post(`/board/Post`, { title, content });

      return res.data;
    } catch (err) {
      console.log(err);
    }
  };

  return (
    <>
      <BtnWrapper>
        <BasicButton
          title={"뒤로 가기"}
          onClickItem={() => {
            navigate("/board");
          }}
        ></BasicButton>
      </BtnWrapper>

      <TextInput
        rows={1}
        placeholder="제목"
        value={title}
        onChange={(event) => {
          setTitle(event.target.value);
        }}
      ></TextInput>

      <TextInput
        rows={14}
        placeholder="내용"
        value={content}
        onChange={(event) => {
          setContent(event.target.value);
        }}
      ></TextInput>

      <BtnWrapper>
        <BasicButton
          title={"글 작성 완료"}
          onClickItem={() => {
            addPost();

            navigate("/board");
          }}
        ></BasicButton>
      </BtnWrapper>
    </>
  );
};

export default PostWritePage;
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.