🔽 이전 글
(Backend) RestBoardController.java detail() 메서드 생성
- /controller/BoardController.java에서 detail() GET 메서드 복사한 후 수정
@GetMapping("/detail/{bno}")
public BoardDto detail(@PathVariable("bno") Long bno, HttpServletRequest request) {
String prevUrl = request.getHeader("referer");//이전 페이지 변수 담기
log.info(String.format("현재 이전 페이지: %s", prevUrl));
Board _board = this.boardService.hitBoard(bno); // 조회수 증가하고 리턴
BoardDto board = BoardDto.builder()
.bno(_board.getBno())
.title(_board.getTitle())
.content(_board.getContent()).createDate(_board.getCreateDate())
.modifyDate(_board.getModifyDate())
.writer(_board.getWriter() != null ? _board.getWriter().getUsername() : "")
.build();
List<ReplyDto> replyList = new ArrayList<>();
if(_board.getReplyList().size() > 0) {
_board.getReplyList().forEach(rpy -> replyList.add(ReplyDto.builder().content(rpy.getContent())
.createDate(rpy.getCreateDate()).modifyDate(rpy.getModifyDate())
.rno(rpy.getRno())
.writer(rpy.getWriter() != null ? rpy.getWriter().getUsername() : "" )
.build()));
}
board.setReplyList(replyList);
return board;
}
(Frontend) /BoardList.js 제목 수정
<Link to={`/boardDetail/${board.bno}`}>{board.title}</Link>
/routes/BoardDetail.js 생성
import { useState } from 'react';
import { useParams } from 'react-router-dom';
function BoardDetail() {
// const [bid, setBid] = useState(0);
const params = useParams();
console.log(params.bno);
// setBid(params.bno);
return (
<div className='container main'>
<h1>boardDetail {params.bid} </h1>
</div>
);
}
export default BoardDetail;
App.js에서 링크 연결
- App.js
import BoardDetail from './routes/BoardDetail';
<Route path='/boardDetail/:bno' element={<BoardDetail />} />
(Back) RestBoardController.java detail() 리턴값 변경
@GetMapping("/detail/{bno}")
public Header<BoardDto> detail(@PathVariable("bno") Long bno, HttpServletRequest request) {
try{
String prevUrl = request.getHeader("referer");//이전 페이지 변수 담기
log.info(String.format("현재 이전 페이지: %s", prevUrl));
Board _board = this.boardService.hitBoard(bno); // 조회수 증가하고 리턴
BoardDto board = BoardDto.builder()
.bno(_board.getBno())
.title(_board.getTitle())
.content(_board.getContent()).createDate(_board.getCreateDate())
.modifyDate(_board.getModifyDate())
.writer(_board.getWriter() != null ? _board.getWriter().getUsername() : "")
.build();
List<ReplyDto> replyList = new ArrayList<>();
if(_board.getReplyList().size() > 0) {
_board.getReplyList().forEach(rpy -> replyList.add(ReplyDto.builder().content(rpy.getContent())
.createDate(rpy.getCreateDate()).modifyDate(rpy.getModifyDate())
.rno(rpy.getRno())
.writer(rpy.getWriter() != null ? rpy.getWriter().getUsername() : "" )
.build()));
}
board.setReplyList(replyList);
return Header.OK(board);
} catch (Exception e) {
return Header.OK(e.getMessage());
}
}
- 404 error가 뜨지 않도록, Header를 리턴으로 넘김
(Front) BoardDetail.js에서 axios로 가져오기
// URL에 넘어온 매개변수
import React, { useState, useEffect, useInsertionEffect } from 'react';
import { Link, useParams } from "react-router-dom";
//RestAPI
import axios from 'axios';
// 공통함수 추가
import * as common from '../common/CommonFunc';
function BoardDetail() {
const [board, setBoard] = useState({}); // 딕셔너리 한번에!
const [replyList, setReplyList] = useState([]);
const params = useParams(null);
console.log(params.bno);
const getBoardDetail = async (bno) => {
const resp = (await axios.get("http://localhost:8080/api/board/detail/" + bno));
const resultCode = resp.data.resultCode;
// console.log(resultCode);
console.log(resp.data.data);
if(resultCode == 'OK') {
setBoard(resp.data.data); // data 내용 한번에
}
if(resp.data.data.replyList.length > 0) {
setReplyList(resp.data.data.replyList);
}
}
// 상세 RestAPI 요청
useEffect(() => {
getBoardDetail(params.bno);
}, []); // useEffect를 사용하지 않으면 무한로딩 발생!!
return (
<div className="container main">
<h4 className="border-bottom py-2">{board.title}</h4>
<div className="card my-3">
<div className="card-body">
<div className="card-text">{board.content}</div>
<div className="d-flex justify-content-end">
{/* <div className="badge bg-light text-dark p-2 text-start mx-3">
<div className="mb-2">modified at</div>
<div></div>
</div> */}
<div className="badge bg-light text-dark p-2 text-start">
<div className="mb-2">
<span>{board.writer}</span>
</div>
<div>{common.formatDate(board.createDate)}</div>
</div>
</div>
<div className="my-3">
</div>
</div>
</div>
<h5 className="border-bottom my-3 py-2">{`${replyList.length}개의 댓글이 있습니다.`}</h5>
{replyList && replyList.map((reply) => (
<div className="card my-3" key={reply.rno}>
<div className="card-body">
<div className="card-text">{reply.content}</div>
<div className="d-flex justify-content-end">
<div className="badge bg-light text-dark p-2 text-start">
<div className="mb-2">
<span>{reply.writer}</span>
</div>
<div>{common.formatDate(reply.createDate)}</div>
</div>
</div>
</div>
</div>
))}
</div>
);
}
export default BoardDetail;
'Spring Boot > STUDY' 카테고리의 다른 글
[Spring] Mapper와 Repository의 차이 (0) | 2024.08.08 |
---|---|
[Spring Boot] 타임리프(Thymeleaf)란? (0) | 2024.07.17 |
[Spring Boot] React연동 프로젝트(3) - 회원가입 및 로그인 기능 구현 (1) | 2024.07.04 |
[Spring Boot] React연동 프로젝트(2) - 페이징 기능 구현 (0) | 2024.07.03 |
[Spring Boot] React연동 프로젝트(1) - 프로젝트 생성 및 리스트 출력 (1) | 2024.07.02 |