페이징

이소연's avatar
Aug 05, 2024
페이징
notion image
notion image
BoardResponse
package shop.mtcoding.blog.board; import lombok.Data; import org.springframework.data.domain.Page; import shop.mtcoding.blog.reply.Reply; import shop.mtcoding.blog.user.User; import java.util.ArrayList; import java.util.List; public class BoardResponse { @Data public static class DTO { private int id; private String title; private String content; public DTO(Board board) { this.id = board.getId(); this.title = board.getTitle(); this.content = board.getContent(); } } // 게시글 상세보기 화면 @Data public static class DetailDTO { private int id; private String title; private String content; private int userId; private String username; // 게시글 작성자 이름 private boolean isOwner; private List<ReplyDTO> replies = new ArrayList<>(); public DetailDTO(Board board, User sessionUser) { this.id = board.getId(); this.title = board.getTitle(); this.content = board.getContent(); this.userId = board.getUser().getId(); this.username = board.getUser().getUsername(); // join 해서 가져왔음 this.isOwner = false; if(sessionUser != null){ if(sessionUser.getId() == userId) isOwner = true; } this.replies = board.getReplies().stream().map(reply -> new ReplyDTO(reply, sessionUser)).toList(); } @Data public class ReplyDTO { private int id; private String comment; private int userId; // 댓글 작성자 아이디 private String username; // 댓글 작성자 이름 private boolean isOwner; public ReplyDTO(Reply reply, User sessionUser) { this.id = reply.getId(); // lazy loading 발동 this.comment = reply.getComment(); this.userId = reply.getUser().getId(); this.username = reply.getUser().getUsername(); // lazy loading 발동 (in query) this.isOwner = false; if(sessionUser != null){ if(sessionUser.getId() == userId) isOwner = true; } } } } // 게시글 목록보기 화면 @Data public static class MainDTO { private int id; private String title; public MainDTO(Board board) { this.id = board.getId(); this.title = board.getTitle(); } } // 게시글 목록보기 화면 @Data public static class MainV2DTO { private Integer totalPage; private Integer number; // 현재 페이지 private Boolean isFirst; private Boolean isLast; private List<BoardDTO> boards; public MainV2DTO(Page<Board> boardPG) { this.totalPage = boardPG.getTotalPages(); this.number = boardPG.getNumber(); this.isFirst = boardPG.isFirst(); this.isLast = boardPG.isLast(); this.boards = boardPG.getContent().stream().map(BoardDTO::new).toList(); } @Data public class BoardDTO { private int id; private String title; public BoardDTO(Board board) { this.id = board.getId(); this.title = board.getTitle(); } } } }
 
BoardService에 추가
public BoardResponse.MainV2DTO 글목록조회V2(Pageable pageable) { Page<Board> boardPG = boardJPARepository.findAll(pageable); return new BoardResponse.MainV2DTO(boardPG); }
notion image
 
BoardController 이 부분으로 덮어씌워
@GetMapping("/") public ResponseEntity<?> mainV2(@PageableDefault(size=3, sort="id", direction = Sort.Direction.DESC) Pageable pageable){ BoardResponse.MainV2DTO respDTO = boardService.글목록조회V2(pageable); return ResponseEntity.ok(new ApiUtil(respDTO)); } // 인증 필요 없음 @GetMapping("/v1") public ResponseEntity<?> main(){ List<BoardResponse.MainDTO> respDTO = boardService.글목록조회(); return ResponseEntity.ok(new ApiUtil(respDTO)); }
바디데이터랑 똑같이 하면 됨.
notion image
 
Home.js
커서 ai post ⇒ board로 고치기
notion image
notion image
notion image
고치셈
notion image
 
detail에서도post⇒ board로 고치기
 
Detail.js
import axios from "axios"; import React, { useEffect, useState } from "react"; import { Button } from "react-bootstrap"; import { Link, useParams } from "react-router-dom"; const Detail = (props) => { const { id } = useParams(); const [board, setBoard] = useState({ id: undefined, title: "", content: "", userId: undefined, username: "", owner: false, replies: [], }); useEffect(() => { fetchDetail(id); }, []); async function fetchDetail(boardId) { let response = await axios({ url: `http://localhost:8080/api/boards/${boardId}/detail`, }); let responseBody = response.data; setBoard(responseBody.body); } function fetchDelete(boardId) {} return ( <div> <Link to={`/updateForm/${board.id}`} className="btn btn-warning"> 수정 </Link> <Button className="btn btn-danger" onClick={() => fetchDelete(board.id)}> 삭제 </Button> <br /> <br /> <h1>{board.title}</h1> <hr /> <div>{board.content}</div> </div> ); }; export default Detail;
 
Home.js
import axios from "axios"; import React, { useEffect, useState } from "react"; import { Pagination } from "react-bootstrap"; import PostItem from "../../components/BoardItem"; const Home = () => { const [page, setPage] = useState(0); const [model, setModel] = useState({ totalPage: undefined, number: undefined, isFirst: true, isLast: false, boards: [], }); // http://localhost:8080 -> http://localhost:8080?page=0 // 실행시점 : 최초 렌더링 // 변경 : page가 바뀌면 useEffect 실행되게 할 예정 useEffect(() => { console.log("useEffect 실행"); apiHome(); }, [page]); async function apiHome() { let response = await axios({ url: "http://localhost:8080?page=" + page, method: "get", }); console.log("page", response.data.body); setModel(response.data.body); } function prev() { setPage(page - 1); } function next() { console.log("next click"); setPage(page + 1); } return ( <div> {model.boards.map((board) => ( <PostItem key={board.id} id={board.id} title={board.title} /> ))} <br /> <div className="d-flex justify-content-center"> <Pagination> <Pagination.Item onClick={prev} disabled={model.isFirst}> Prev </Pagination.Item> <Pagination.Item onClick={next} disabled={model.isLast}> Next </Pagination.Item> </Pagination> </div> </div> ); }; export default Home;
 
Share article

Coding's note