본문 바로가기
Library&Framework/React

[리액트 강의 복습 03] 리액트에서 map 을 이용한 게시글 리스트 보기 , 게시글 작성하기

by 우지uz 2024. 1. 4.

게시글 전체 

const [posts, setPosts] = useState([
    {
      id: 1,
      title: "남자 코트 추천 해드립니다!",
      content: "이 코트는 모의 회사에서 개발한 코트입니다.",
      publishDate: "2023-01-01",
      likes: 0,
    },
    {
      id: 2,
      title: "강남 우동 맛집 소개!",
      content: "이 우동집은 모의 회사에서 개발한 우동집입니다.",
      publishDate: "2023-01-02",
      likes: 0,
    },
    {
      id: 3,
      title: "파이썬 독학하는 방법좀 알려주세요",
      content: "파이썬을 독학하려면 어떻게 해야할까요? ",
      publishDate: "2023-01-03",
      likes: 0,
    },
]);

App 함수의 return 에 컴포넌트 넣어주기 

return (
    위 코드 생략
      {posts.map((post, index) => (
        <div className="list" key={post.id} style={{ width: "65%" }}>
          <PostCategory
            id={post.id}
            title={post.title}
            content={post.content}
            publishDate={post.publishDate}
            likes={post.likes}
            onLikeClick={() => incrementLikes(index)}
            onToggleModal={() => toggleModal(index)}
            onDeleteClick={() => deletePost(post.id)}
          />
        </div>
      ))}
      아래 코드 생략
);

onLikeClick 과 같은 함수를 클릭하면, incrementLikes 함수를 실행하도록 되어있다. 

function App() {
  const [posts, setPosts] = useState([
    {
      id: 1,
      title: "남자 코트 추천 해드립니다!",
      content: "이 코트는 모의 회사에서 개발한 코트입니다.",
      publishDate: "2023-01-01",
      likes: 0,
    },
    {
      id: 2,
      title: "강남 우동 맛집 소개!",
      content: "이 우동집은 모의 회사에서 개발한 우동집입니다.",
      publishDate: "2023-01-02",
      likes: 0,
    },
    {
      id: 3,
      title: "파이썬 독학하는 방법좀 알려주세요",
      content: "파이썬을 독학하려면 어떻게 해야할까요? ",
      publishDate: "2023-01-03",
      likes: 0,
    },
  ]);
  const getCurrentDate = () => {
    const currentDate = new Date();
    const year = currentDate.getFullYear();
    const month = String(currentDate.getMonth() + 1).padStart(2, "0");
    const day = String(currentDate.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
  };
  const [newPost, setNewPost] = useState({
    id: posts.length + 1, // Generating a new id for the new post
    title: "",
    content: "",
    publishDate: getCurrentDate(), // Assuming you want to set the current date
    likes: 0,
  });

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setNewPost((prevPost) => ({
      ...prevPost,
      [name]: value,
    }));
  };
  const addNewPost = () => {
    setPosts((prevPosts) => [...prevPosts, newPost]);
    setNewPost({
      id: posts.length + 2,
      title: "",
      content: "",
      publishDate: getCurrentDate(),
      likes: 0,
    });
  };
  const [isModalVisible, setModalVisibility] = useState(false);
  const [modalIndex, setModalIndex] = useState(0);
  //   let [changeValue, setChangeValue] = useState("");
  const changeTitle = (index) => {
    const updatedPosts = [...posts];
    updatedPosts[modalIndex].title += " 새로운";
    setPosts(updatedPosts);
  };

  const toggleModal = (index) => {
    setModalVisibility(!isModalVisible);
    setModalIndex(index);
  };

  const incrementLikes = (index) => {
    const updatedPosts = [...posts];
    updatedPosts[index].likes += 1;
    setPosts(updatedPosts);
  };
  const deletePost = (postId) => {
    const updatedPosts = posts.filter((post) => post.id !== postId);
    setPosts(updatedPosts);
  };

  return (
    <div className="App d-flex flex-column align-items-center">
      <div className="black-nav main-head-height d-flex align-items-center justify-content-center">
        <img
          src={logo}
          alt="ReactBlog Logo"
          className="logo-img"
          style={{ width: "50px", height: "50px", marginRight: "10px" }}
        />
        <h4>ReactBlog</h4>
      </div>

      {posts.map((post, index) => (
        <div className="list" key={post.id} style={{ width: "65%" }}>
          <PostCategory
            id={post.id}
            title={post.title}
            content={post.content}
            publishDate={post.publishDate}
            likes={post.likes}
            onLikeClick={() => incrementLikes(index)}
            onToggleModal={() => toggleModal(index)}
            onDeleteClick={() => deletePost(post.id)}
          />
        </div>
      ))}
      {isModalVisible === true ? (
        <Modal
          isVisible={isModalVisible}
          title={posts[modalIndex].title}
          postDate={posts[modalIndex].publishDate}
          postContent={posts[modalIndex].content}
          skyblue={"skyblue"}
          changeTitle={() => changeTitle(modalIndex)} // changeTitle 함수를 props로 내려줌
          toggleModal={() => toggleModal(modalIndex)} // toggleModal 함수를 props로 내려줌
          modalIndex={modalIndex}
        ></Modal>
      ) : null}
      <div
        className="list text-center"
        style={{ width: "65%", margin: "0 auto" }}
      >
        {/* ... (이전 코드 유지) */}
        {/* 새로운 게시글 입력 폼 */}
        <div className="mb-3">
          <label htmlFor="postTitle" className="form-label">
            제목
          </label>
          <input
            type="text"
            className="form-control"
            id="postTitle"
            name="title"
            value={newPost.title}
            onChange={handleInputChange}
          />
        </div>
        <div className="mb-3">
          <label htmlFor="postContent" className="form-label">
            내용
          </label>
          <textarea
            className="form-control"
            id="postContent"
            name="content"
            rows="3"
            value={newPost.content}
            onChange={handleInputChange}
          ></textarea>
        </div>
        <button className="btn btn-primary mb-5" onClick={addNewPost}>
          새로운 게시글 추가
        </button>
      </div>
      {/* <input
        className="m-5"
        onChange={(e) => {
          setChangeValue(e.target.value);
          console.log(e.target.value);
        }}
      ></input> */}
      <div className="mt-5 black-nav main-head-height d-flex flex-column align-items-center justify-content-center">
        <h4>ReactBlog</h4>
      </div>
    </div>
  );
}

대부분 함수들은, State 를 통해 변수들을 변경해주고 있다. 

 

게시글을 추가하는 양식을 추가해보았다.

제목과 내용을 입력하면, 게시글이 추가된다. 

html 은 다음과 같이 리턴해주었고 

<div
    className="list text-center"
    style={{ width: "65%", margin: "0 auto" }}
  >
    {/* ... (이전 코드 유지) */}
    {/* 새로운 게시글 입력 폼 */}
    <div className="mb-3">
      <label htmlFor="postTitle" className="form-label">
        제목
      </label>
      <input
        type="text"
        className="form-control"
        id="postTitle"
        name="title"
        value={newPost.title}
        onChange={handleInputChange}
      />
    </div>
    <div className="mb-3">
      <label htmlFor="postContent" className="form-label">
        내용
      </label>
      <textarea
        className="form-control"
        id="postContent"
        name="content"
        rows="3"
        value={newPost.content}
        onChange={handleInputChange}
      ></textarea>
    </div>
    <button className="btn btn-primary mb-5" onClick={addNewPost}>
      새로운 게시글 추가
    </button>
</div>

새로운 글을 작성하는 State 에 대해서는 

const getCurrentDate = () => {
    const currentDate = new Date();
    const year = currentDate.getFullYear();
    const month = String(currentDate.getMonth() + 1).padStart(2, "0");
    const day = String(currentDate.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
  };
  const [newPost, setNewPost] = useState({
    id: posts.length + 1, // Generating a new id for the new post
    title: "",
    content: "",
    publishDate: getCurrentDate(), // Assuming you want to set the current date
    likes: 0,
  });

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setNewPost((prevPost) => ({
      ...prevPost,
      [name]: value,
    }));
  };
  const addNewPost = () => {
    setPosts((prevPosts) => [...prevPosts, newPost]);
    setNewPost({
      id: posts.length + 2,
      title: "",
      content: "",
      publishDate: getCurrentDate(),
      likes: 0,
    });
};

id, 게시날짜, likes 는 자동으로 만들어주고 

입력받은 title 과 content는 

handleInputChange 함수를 통해서 

변경해주었다.