본문 바로가기
팀프로젝트_기록일지/React복습용글

(1)React_배열Render, sort,delete

by 코잼민 2025. 1. 2.

● 복습1_fetch + 배열 render하기

○ App.js

import { useState } from "react";
import ReviewList from "./ReviewList";
import { getReviews } from "../api";

function App() {
  const [items, setItems] = useState([]);

  const handleLoadClick = async () => {
    const { reviews } = await getReviews();

    setItems(reviews);
  };

  return (
    <div>
      <ReviewList items={items} />
      <button onClick={handleLoadClick}>불러오기</button>
    </div>
  );
}

export default App;

○ ReviewList.js

import "./ReviewList.css";

function formatDate(value) {
  const date = new Date(value);
  return `${date.getFullYear()}. ${date.getMonth() + 1}. ${date.getDate()}`;
}

function ReviewListItem({ item }) {
  return (
    <div className="ReviewListItem">
      <img className="ReviewListItem-img" src={item.imgUrl} alt={item.title} />
      <div>
        <h1>{item.title}</h1>
        <p>{item.rating}</p>
        <p>{formatDate(item.createdAt)}</p>
        <p>{item.content}</p>
      </div>
    </div>
  );
}

function ReviewList({ items }) {
  const renderItems = items.map((item) => {
    return (
      <li key={item.id}>
        <ReviewListItem item={item} />
      </li>
    );
  });

  return <ul>{renderItems}</ul>;
}

export default ReviewList;

○ api.js

export async function getReviews() {
  const response = await fetch("https://learn.codeit.kr/api/film-reviews");
  const body = await response.json();
  return body;
}

● 복습2_최신순 , 베스트순 으로 정렬해주는 버튼기능 추가

○ App.js

import { useState } from "react";
import ReviewList from "./ReviewList";
import { getReviews } from "../api";

function App() {
  const [items, setItems] = useState([]);
  //초기 정렬 순서 : 등록된 기간 순순
  const [order, setOrder] = useState("createdAt");

  //정렬된 items를 따로 변수 초기화
  const sortReviews = items.sort((a, b) => {
    return b[order] - a[order];
  });

  const handleLoadClick = async () => {
    const { reviews } = await getReviews();

    setItems(reviews);
  };

  //최신순, 베스트순 버튼의 핸들러 구현
  const handleRatingSort = () => {
    setOrder("rating");
  };

  const handleCreatedAtSort = () => {
    setOrder("createdAt");
  };

  return (
    <div>
      <div>
        <button onClick={handleCreatedAtSort}>최신순</button>
        <button onClick={handleRatingSort}>베스트트순</button>
      </div>
      <ReviewList items={sortReviews} />
      <button onClick={handleLoadClick}>불러오기</button>
    </div>
  );
}

export default App;

● 복습3_삭제버튼 추가

○ App.js

  • filter 적용 콜백함수 추가 : handleDelete 메소드
  • ReviewList 컴포넌트의 onDelete속성으로 handleDelete전달
import { useState } from "react";
import ReviewList from "./ReviewList";
import { getReviews } from "../api";

function App() {
  const [items, setItems] = useState([]);
  const [order, setOrder] = useState("createdAt");

  const sortReviews = items.sort((a, b) => {
    return b[order] - a[order];
  });

  const handleLoadClick = async () => {
    const { reviews } = await getReviews();

    setItems(reviews);
  };

  const handleRatingSort = () => {
    setOrder("rating");
  };

  const handleCreatedAtSort = () => {
    setOrder("createdAt");
  };

  //삭제 버튼 핸들러 등록
  const handleDeleteReview = (id) => {
    const deleteAfterReviews = items.filter((item) => id !== item.id);
    //filter 메소드 작성할 때, 문법 조심

    setItems(deleteAfterReviews);
  };


  return (
    <div>
      <div>
        <button onClick={handleCreatedAtSort}>최신순</button>
        <button onClick={handleRatingSort}>베스트트순</button>
      </div>
      <ReviewList items={sortReviews} onDelete={handleDeleteReview} />
      //컴포넌트 onDelete 속성으로 전달
      <button onClick={handleLoadClick}>불러오기</button>
    </div>
  );
}

export default App;

○ ReviewList.js

import "./ReviewList.css";

function formatDate(value) {
  const date = new Date(value);
  return `${date.getFullYear()}. ${date.getMonth() + 1}. ${date.getDate()}`;
}

function ReviewListItem({ item, onDelete }) {
  const handleDeleteFilm = () => onDelete(item.id);
  //삭제 버튼 핸들러 등록

  return (
    <div className="ReviewListItem">
      <img className="ReviewListItem-img" src={item.imgUrl} alt={item.title} />
      <div>
        <h1>{item.title}</h1>
        <p>{item.rating}</p>
        <p>{formatDate(item.createdAt)}</p>
        <p>{item.content}</p>
      </div>
      <div>
        <button onClick={handleDeleteFilm}>삭제</button>
        //삭제버튼 onClick에 등록
      </div>
    </div>
  );
}

function ReviewList({ items, onDelete }) {
  const renderItems = items.map((item) => {
    return (
      <li key={item.id}>
        <ReviewListItem item={item} onDelete={onDelete} />
      </li>
    );
  });

  return <ul>{renderItems}</ul>;
}

export default ReviewList;

 

● 복습4_fetch를 불러오기 버튼 없이 자동 fetch하게끔 하기

○ App.js

  • 'react'에서 import {useEffect} 추가하기
  • 버튼 핸들러가 아닌, 그냥 loadFetchReview 메소드 초기화
  • useEffect의 콜백 메소드에 loadFetchReview() 호출
import { useState, useEffect } from "react"; //useEffect 추가하기기
import ReviewList from "./ReviewList";
import { getReviews } from "../api";

function App() {
  const [items, setItems] = useState([]);
  const [order, setOrder] = useState("createdAt");

  const loadReviews = async () => {
    const { reviews } = await getReviews();

    setItems(reviews);
  };

  useEffect(() => {
    loadReviews();
  }, []);

  const sortReviews = items.sort((a, b) => {
    return b[order] - a[order];
  });

  const handleRatingSort = () => {
    setOrder("rating");
  };

  const handleCreatedAtSort = () => {
    setOrder("createdAt");
  };

  const handleDeleteReview = (id) => {
    const deleteAfterReviews = items.filter((item) => id !== item.id);

    setItems(deleteAfterReviews);
  };

  return (
    <div>
      <div>
        <button onClick={handleCreatedAtSort}>최신순</button>
        <button onClick={handleRatingSort}>베스트트순</button>
      </div>
      <ReviewList items={sortReviews} onDelete={handleDeleteReview} />
    </div>
  );
}

export default App;

▶ 출력 결과 : 브라우저 "개발자 도구 창의 network탭 확인" :

● 복습5_query를 이용하여, Api에서 정렬된 데이터를 fetch하기

○ api.js :

  • fetch하는 Get 메소드의 매개인자 order 문자열값 추가
  • query문자열을 따로 변수 초기화 + 매개인자 대입
  • fetch()메소드의 매개인자인 url에 ? + query 문자열 적용
//매개인자에 order 추가
export async function getReviews(order = "createdAt") {
  const query = `order=${order}`;
  //Get메소드에 query문자열 따로 추가

  const response = await fetch(
    `https://learn.codeit.kr/api/film-reviews?${query}`
  );
  //fetch의 url에 query작용
  const body = await response.json();
  return body;
}

○ App.js :

  • Get 메소드와 관련된 부분들 모두 수정 :
import { useState, useEffect } from "react"; //useEffect 추가하기기
import ReviewList from "./ReviewList";
import { getReviews } from "../api";

function App() {
  const [items, setItems] = useState([]);
  const [order, setOrder] = useState("createdAt");

  //Get 메소드 있는 부분 모두 수정 :

  //loadReviews
  const loadReviews = async (orderQuery) => {
    const { reviews } = await getReviews(orderQuery);

    setItems(reviews);
  };

  //useEffect 부분
  useEffect(() => {
    loadReviews(order);
  }, [order]);

  const sortReviews = items.sort((a, b) => {
    return b[order] - a[order];
  });

  const handleRatingSort = () => {
    setOrder("rating");
  };

  const handleCreatedAtSort = () => {
    setOrder("createdAt");
  };

  const handleDeleteReview = (id) => {
    const deleteAfterReviews = items.filter((item) => id !== item.id);

    setItems(deleteAfterReviews);
  };

  return (
    <div>
      <div>
        <button onClick={handleCreatedAtSort}>최신순</button>
        <button onClick={handleRatingSort}>베스트트순</button>
      </div>
      <ReviewList items={sortReviews} onDelete={handleDeleteReview} />
    </div>
  );
}

export default App;

○ 출력 결과 :

Fetch 메시지의 쿼리문이 달라진 것을 알 수 있고, 즉, Api에서 정렬된 데이터를 불러왔다는 것을 알 수 있다.

 

'팀프로젝트_기록일지 > React복습용글' 카테고리의 다른 글

TodoList_복습1  (0) 2025.01.18