고래씌
[React] 7. REST 본문
1. REST
REST(Represntational State Transfer) : URL과 전송방법(Method)을 활용하여 작업내용을 url창에 표현하고, 필요한 상태를 전달하는 모든 행위를 의미한다.
/board/detail → /board/detail/5(get) board에서 5번게시물을 조회해와라. 내가 하고자하는 것을 url에 모두 표시하는 것! |
- BoardDetail.js, BoardUpdate.js, BoardInsert.js, BoardList.js 모두 공통적으로 들어가있는 태그이다. 이거는 따로 컴포넌트에서 만들어서 사용해보도록 하겠다!
=> 저 태그를 지우고 <></>로 묶어줘야 오류가 발생하지 않는다.
▶ components 폴더아래에 Outer.js 파일을 생성해주고 지웠던 태그들을 복붙하여 아래와 같이 기술
import {Outlet} from "react-router-dom"
export default function Outer(){
return (
<div classNmae="outer">
<br/>
<Outlet></Outlet>
</div>
)
}
|
▶ App.js에서 이런방법으로 (상대경로) 전송할 것이기 때문에 모두 경로 변경해준다.
=> 라우트 파라미터 문법
/: 매개변수명
중첩으로 여러개 작성도 가능
▶ App.js
=> 상세보기와 상세보기변경 지움
/* eslint-disable */
//콘솔창에 불필요한 에러를 지우는 코드
import './App.css';
import {useState} from 'react';
import 초기게시글 from './data'; //default옵션으로 export한 경우 변수명을 다르게 가져올 수 있음
import {a,b,c} from './data'; //a,b,c의 값을 가지고 옴
import BoardInsert from './pages/BoardInsert';
import BoardList from './pages/BoardList';
import BoardDetail from './pages/BoardDetail';
import BoardUpdate from './pages/BoardUpdate';
import { Route, Routes, Link } from 'react-router-dom';
import Outer from './components/Outer';
function App() {
// state 문법
let [제목2, 제목변경함수] = useState('KH E CLASS');
let [게시글배열, 게시글배열변경함수] = useState(초기게시글);
//2) 레이아웃상태를 state로 저장시키기
let [레이아웃, 레이아웃변경] = useState(0);
function 제목2변경 (){
// 제목2 = "KH C CLASS"; // 단순 대입연산자를 활용하는 경우 state값의 변경점을 reactDom이 알지못함
제목변경함수("KH C CLASS"); //useState의 두번째 매개변수로 전달받은 함수를 통해 변경 시 화면이 재랜더링됨
}
// let [상세보기, 상세보기변경] = useState(null); // 각 게시글 정보 담아줄 예정
let 등록페이지url = "/insert";
// let 모든데이터 = {
// 게시글배열, 게시글배열변경함수, 상세보기, 상세보기변경
// }
let 모든데이터 = {
게시글배열, 게시글배열변경함수
}
return (
<div className="App">
<div className="header">
<h3 style={ {fontWeight : "bolder"} }> {제목2} </h3>
</div>
<div className='nav'>
{/* <button onClick={function(){ // ui상태관리 -3) state변경함수를 버튼등의 요소에 부여
레이아웃변경(0);
}}> 게시판 </button>
<button onClick={function(){
레이아웃변경(1);
}}> 등록 </button> */}
<Link to="/board/list">게시판</Link> {/* a태그로 하면 get방식&비동기. 데이터반영안됨 link로연결 */}
<Link to={"/board"+등록페이지url} >등록</Link>{/* 리액트전용 a태그 */}
</div>
<Routes>
<Route path='/' element={ <BoardList 모든데이터={모든데이터} /> } />
<Route path="/board" element={<Outer/>}>
{/* 하위요소는 /board/list 가 됨 */}
<Route path='list' element={<BoardList 모든데이터={모든데이터} />}/>
<Route path='insert' element={<BoardInsert 모든데이터={모든데이터} />}/>
{/*
라우트 파라미터 문법
/: 매개변수명
중첩으로 여러개 작성도 가능
*/}
<Route path="detail/:bno" element={<BoardDetail 모든데이터={모든데이터} />}/>
<Route path='update/:bno' element={<BoardUpdate 모든데이터={모든데이터} />}/>
</Route>
{/* 위에꺼 제외한 모든 페이지, 맨 아래쪽에 위치해야함 */}
<Route path='*' element={
<div>
<h1 style={ {color : "red" }} > 존재하지 않는 페이지입니다. </h1>
<Link to='/'> 사이트로 돌아가기 </Link>
</div>
}/>
</Routes>
</div>
);
}
export default App;
▶ BoardDetail.js 경로 수정
=> url 창에 글번호 뽑아오는 법
=> 동일한 파라미터명으로 변수 호출하면됨
const {bno} = useParams(); // /:파라미터명
|
=> 상세보기 불러오는 코드 변경
=> bno를 활용해서 게시글배열에서 내가 bno와 일치하는 게시글을 찾아서 넣어주기
=> 경로 변경
<Link to={'/board/update/' + 상세보기.글번호}>수정</Link>
|
import { Link, useParams } from 'react-router-dom';
export default function BoardDetail({모든데이터}){
// url창에 글번호 뽑아오는 법
const {bno} = useParams(); // /:파라미터명
// 동일한 파라미터명으로 변수 호출하면됨
console.log(bno);
// 상세보기 불러오는 코드 변경
// bno를 활용해서 게시글배열에서 내가 bno와 일치하는 게시글을 찾아서 넣어주기
// let{상세보기} = 모든데이터;
let 상세보기 = 모든데이터.게시글배열.find( function(게시글) {
return 게시글.글번호 == bno;
});
return(
<>
<table className='detail-table'>
<tr>
<th colSpan={4}>{상세보기.글제목}</th>
</tr>
<tr>
<th>작성자</th>
<td>{상세보기.작성자}</td>
<th>작성일</th>
<td>{상세보기.작성일}</td>
</tr>
<tr>
<th>글내용</th>
<td colSpan={3} style={{ height: "200px" }}>{상세보기.글내용}</td>
</tr>
</table>
<div className='btn-area'>
<Link to={'/board/update/' + 상세보기.글번호}>수정</Link>
</div>
</>
)
}
▶ BoardUpdate.js 경로 수정
=> 경로변경
navigate('/board/detail/' + 입력값.글번호); // 상대경로방식으로 이동
|
=> 상세보기변경 주석
import {useState} from 'react';
import { useNavigate, useParams } from 'react-router-dom';
export default function BoardUpdate({모든데이터}){
const navigate = useNavigate();
// 상세보기, 배열
// let {게시글배열, 게시글배열변경함수, 상세보기, 상세보기변경} = 모든데이터;
let {게시글배열, 게시글배열변경함수} = 모든데이터;
let {bno} = useParams(); // {bno : 1}
// let 상세보기 = 게시글배열.find(게시글 => {
// return 게시글.글번호 == bno
// })
let 상세보기 = 게시글배열.find(게시글 => 게시글.글번호 == bno);
let [입력값, 입력값변경] = useState(상세보기);
// detail에서 가져왔던 상세보기 정보를 그대로 가져와줌
console.log(입력값);
function 게시글수정(){
// 수정 완료 후 게시글 상세페이지로 이동
let {글제목, 글내용, 작성자} = 입력값;
if(!글제목 || !글내용 || !작성자){
alert("뭐든 입력하세요");
return;
}
const 변경된게시글배열 = 게시글배열.map(function(게시글){
if(게시글.글번호 == 입력값.글번호) return 입력값; // 일치한다면 입력값 반환
return 게시글; // 일치하지 않는다면 게시글 반환
})
게시글배열변경함수([...변경된게시글배열]); // [...변경된게시글배열] 2차원이 배열이 될수 있어서 ()를 붙여야 배열이된다.
// 레이아웃변경(2);
// 상세보기변경(입력값);
navigate('/board/detail/' + 입력값.글번호); // 상대경로방식으로 이동
}
// 입력했던 값들이 알맞게 추가될 것
function onIputHandler(e){
let {name , value} = e.target;
입력값변경({...입력값, [name] : value});
}
return (
<>
<table className='enroll-table'>
<tr>
<th>제목</th>
<td colSpan={3}>
<input type='text' name='글제목'
onChange={onIputHandler}
value={입력값.글제목}
/>
</td>
</tr>
<tr>
<th>작성자</th>
<td colSpan={3}>
<input type='text' name='작성자'
onChange={onIputHandler}
value={입력값.작성자}
/>
</td>
</tr>
<tr>
<th>글내용</th>
<td colSpan={3} style={ { height: "200px" } }>
<textarea name='글내용'
onChange={onIputHandler}
value={입력값.글내용}
></textarea>
</td>
</tr>
<tr>
<th colSpan={4}><button onClick={ 게시글수정}>수정</button></th>
</tr>
</table>
</>
)
}
▶ BoardInsert.js 경로 수정
=> 경로변경
navigate('/board/list'); // 상대경로방식으로 이동
|
import { useState } from "react";
import { useNavigate } from "react-router-dom";
export default function BoardInsert({모든데이터}){
let {게시글배열 , 게시글배열변경함수} = 모든데이터;
const navigate = useNavigate();
let [입력값, 입력값변경] =useState({글제목 : "",
글내용 : "",
작성자 : ""});
// 입력값.글제목
function 게시글등록 () {
let {글내용 , 글제목, 작성자} = 입력값;
if( !글내용 || !글제목 || !작성자 ){
alert("뭐든 입력하십쇼");
return;
}
//2) 가져온 데이터를 바탕으로 게시글 객체 생성하기
let 게시글 = {
//글번호는 게시글배열에서 고유해야함. 게시글배열에서 가장큰 글번호값을 찾은후 +1해서 반환해줄 예정.
글번호 : Math.max( ...게시글배열.map( function(게시글, 인덱스) {return 게시글.글번호})) +1,
...입력값, // 한줄로 키밸류값으로 가져옴
작성일 : new Date().toLocaleDateString() // 2024. 01. 15
}
//3) 생성한 게시글객체를 게시글배열에 추가한 후 , 게시글배열변경함수 호출하기(랜더링)
게시글배열변경함수([...게시글배열 , 게시글]);
//입력값 초기화(state초기화)
입력값변경({
글제목 : "",
글내용 : "",
작성자 : ""
})
navigate('/board/list'); // 상대경로방식으로 이동
}
function onIputHandler(e){
let {name , value} = e.target;
입력값변경({...입력값, [name] : value});
}
return (
<>
<table className='enroll-table'>
<tr>
<th>제목</th>
<td colSpan={3}>
<input type='text' name='글제목'
onChange={function(e){
입력값변경({...입력값, 글제목 : e.target.value});
}}
value={입력값.글제목} // 입력값 내부에 있는 글제목값을 가져와라
/>
</td>
</tr>
<tr>
<th>작성자</th>
<td colSpan={3}>
<input type='text' name='작성자'
onChange={function(e){
console.dir(e.target)
입력값변경({
...입력값 ,
[e.target.name] : e.target.value // 입력하고자하는 값은 뒤에 놔야함
// [] 표기법을 통해 속성명을 지정해줘야함. [e.target.name]에는 작성자가 들어감
})
}}
value={입력값.작성자} // 입력값 내부에 있는 작성자값을 가져와라
/>
</td>
</tr>
<tr>
<th>글내용</th>
<td colSpan={3} style={ { height: "200px" } }>
<textarea name='글내용'
onChange={onIputHandler}
value={입력값.글내용}
></textarea>
</td>
</tr>
<tr>
<th colSpan={4}><button onClick={게시글등록}>등록</button></th>
</tr>
</table>
</>
)
}
//export default BoardInsert;
▶ BoardList.js 경로 수정
=> 상세보기변경 주석처리
=> 경로수정
navigate('/board/detail/' + 조회할글번호);
|
import { useNavigate } from "react-router-dom";
export default function BoardList({모든데이터}){
// console.log(props);
// let {게시글배열, 게시글배열변경함수, 상세보기변경} = 모든데이터;
let {게시글배열, 게시글배열변경함수} = 모든데이터;
const navigate = useNavigate();
function 게시글삭제(삭제할글번호) {
//2) 게시글배열에서 글번호와 일치하지 않는 게시글만 필터링하기. (filter함수 이용)
let 필터링배열 = 게시글배열.filter( function(게시글) {
return 게시글.글번호 !== 삭제할글번호;
});
게시글배열변경함수(필터링배열);
}
function 게시글상세조회(조회할글번호) {
let 상세게시글 = 게시글배열.find( function(게시글) {
return 게시글.글번호 == 조회할글번호;
});
// 레이아웃변경(2);
// navigate로 이동하고자 하는 페이지 적어주면됨
navigate('/board/detail/' + 조회할글번호);
// 상세보기변경(상세게시글);
}
return (
<>
<table className='list-table'>
<thead>
<tr>
<th style={ {width : "10%" } }>번호</th>
<th style={ {width : "40%" } }>제목</th>
<th style={ {width : "20%" } }>작성자</th>
<th style={ {width : "20%" } }>작성일</th>
<th style={ {width : "10%" } }>삭제</th>
</tr>
</thead>
<tbody>
{/*
Array내부의 map함수 사용 예정
[1,2,3].map(function () { return 1}) ==> [1,1,1]
*/
게시글배열.map(function( 게시글, 인덱스) {
return (
<tr key={인덱스} onClick={ () => 게시글상세조회(게시글.글번호)}>
{/* <tr key={인덱스} onClick={ () => */}
{/* {navigate('/board/detail' + 게시글.글번호); */}
{/* 상세보기변경(게시글); */}
{/* }}> */}
<td>{게시글.글번호}</td>
<td>{게시글.글제목}</td>
<td>{게시글.작성자}</td>
<td>{게시글.작성일}</td>
<td><button onClick={(e) => {
e.stopPropagation(); // 이벤트 전파 방지
게시글삭제(게시글.글번호)}}
>삭제</button>
</td>
</tr>
)
})
}
</tbody>
</table>
</>
)
}
- 해당목록에서 첫번째 게시글을 클릭했을때 다음과 같이 url이 변경됐음을 확인할 수 있다.
▶ 결과
'React > node.js' 카테고리의 다른 글
[React] 9. axios, ContextApi (0) | 2024.01.17 |
---|---|
[React] 8. useEffect (0) | 2024.01.17 |
[React] 6. 라우터 (0) | 2024.01.16 |
[React] 5-2. 게시글 수정 (0) | 2024.01.16 |
[React] 5-1. 게시판 상세페이지 조회 (0) | 2024.01.16 |