2021. 7. 12. 23:46ㆍfront-end/React
// Create - POST
//Read - GET
//Update - PUT
//Delete - DELETE
나는 지금 단어장을 만들면서 단어의 생성, 읽기, 업뎃, 삭제에 대해 배우고 있고, 데이터 값은 json 형식으로 가져오고,
진짜 서버를 이용하는 것이 아니라, json-server 를 이용해 dummy data(?) 를 useFetch( )로 가져오는 것까지 했었다.
1. PUT 우선 해당 날짜에 있는 단어리스트들의 체크박스에 체크하면 체크한 값이 새로고침(F5) 했을 시에도 유지되도록 해줬다. 실제 data.json 에서 데이터 값이 삭제되게끔 해주었다.
// import dummy from '../db/data.json';
import { useState } from 'react';
export default function Word({ word:w }){
//초깃값 처음에는 단어가 보이지 않아야함.
const [word, setWord] = useState(w);
const [isShow, setIsShow] = useState(false);
const [isDone, setIsDone] = useState(word.isDone);
function toggleShow(){
setIsShow(!isShow);
}
function toggleDone(){
// setIsDone(!isDone);
fetch(`http://localhost:3001/words/${word.id}`,{//요청의 옵션들 입력
method:'PUT',
headers:{//Content-Type 은 보내는 리소스의 타입을 의미
'Content-Type' : 'application/json',
},
body :JSON.stringify({//json 문자열로 반환하기 위해 사용
...word,
isDone: !isDone,
}),
}).then( res => { //응답 OK 이면 state 를 if 조건문
if(res.ok){
setIsDone(!isDone);
}
});
}
return(
<tr className={isDone ? 'off':''}>
<td><input type="checkbox" checked={ isDone} onChange={toggleDone}/></td>
<td >{word.eng}</td>
<td >{isShow && word.kor}</td>
<td>
<button onClick={toggleShow}>뜻 {isShow ? '숨기기': '보기'}</button>
<button className="btn_del" onClick={del}>삭제</button>
</td>
</tr>
);
}
// Create - POST
//Read - GET
//Update - PUT
//Delete - DELETE
fetch ( ( url 경로 ),{ } ) 문법 안에
method :
Method는 HTTP method와 동일한 스팩으로 들어가면 된다. GET/POST/HEAD/PUT/DELETE/OPTION/PATH 등등
headers: headers 는 Request Header를 지정해주는 곳인데, 2가지 형식으로 넣을 수 있다.
Object lireral과 Headers 객체의 인스턴스를 넣을 수 있다.
body : body는 HTTP Request에 실을 데이터인데 여러가지 타입을 넣을 수 있다.
즉, 전달하고자 하는 응답 내용이다. 백엔드와 통신할 때는 객체로 통신하기 때문에 객체타입으로 작성해야 한다.
단, JSON 데이터값을 가져와야 하기 때문에 json 문자열로 반환하기 위해 사용
JSON.stringify({ })
*Content-Type 이란..
Content-Type 개체 헤더는 리소스의 media type을 나타내기 위해 사용됩니다.
응답 내에 있는 Content-Type 헤더는 클라이언트에게 반환된 컨텐츠의 컨텐츠 유형이 실제로 무엇인지를 알려줍니다. 브라우저들은 어떤 경우에는 MIME 스니핑을 해서 이 헤더의 값을 꼭 따르지는 않을 겁니다; 이를 막기 위해, X-Content-Type-Options (en-US) 헤더를 nosniff으로 설정할 수 있습니다.
요청 내에서, (POST 혹은 PUT처럼), 클라이언트는 서버에게 어떤 유형의 데이터가 실제로 전송됐는지를 알려줍니다.
[출처]: https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Type
2. DELETE 삭제할 때, 데이터 값을 삭제하는 것이기 때문에 window.confirm( ) 메소드를 사용하여 메시지를 지정할 수 있는 모달 대화 상자를 띄었다.
method: ' DELETE ' 를 해줬고,
function del(){
if(window.confirm('삭제하시겠습니까?')){
fetch(`http://localhost:3001/words/${word.id}`,{
method:'DELETE',
}).then(res=>{
if(res.ok){
setWord({id:0});
}
});
}
}
if(word.id === 0) {
return null;
}
return(
<tr className={isDone ? 'off':''}>
<td><input type="checkbox" checked={ isDone} onChange={toggleDone}/></td>
<td >{word.eng}</td>
<td >{isShow && word.kor}</td>
<td>
<button onClick={toggleShow}>뜻 {isShow ? '숨기기': '보기'}</button>
<button className="btn_del" onClick={del}>삭제</button>
</td>
</tr>
);
}
id 값 0 으로 주고 id 가 0 이면 null 값을 반환해서 바로 단어리스트에서 사라지도록 조건을 걸어주었고,
button태그에 onClick={del} 을 해줌,.
3. Header.jsx 파일과 CreateWord, CreateDay 파일을 새로 생성해 그 생성된 곳에 단어를 추가할 form 을 작성해주고, Day도 추가한다.
import { Link } from "react-router-dom";
export default function Header(){
return(
<div className="header">
<h1 style={{textAlign:"center",}}>
<Link to="/" style={{color:"#fff",margin:"0 auto",}}>토익 영단어(고급)</Link>
</h1>
<div className="menu">
<Link to="/create_word" className="link">단어 추가</Link>
<Link to="/create_day" className="link">Day 추가</Link>
</div>
</div>
);
}
4. CREATE CreateWord / CreateDay jsx 파일
여기서 사용할 것은 useHistory( ) / useRef( ) 라는 리액트 라우터 API 기능이다.
*useRef
JavaScript 를 사용 할 때에는, 우리가 특정 DOM 을 선택해야 하는 상황에 getElementById, querySelector 같은 DOM Selector 함수를 사용해서 DOM 을 선택합니다. 함수형 컴포넌트에서 ref 를 사용 할 때에는 useRef 라는 Hook 함수를 사용합니다. useRef() 를 사용하여 Ref 객체를 만들고, 이 객체를 우리가 선택하고 싶은 DOM 에 ref 값으로 설정해주어야 합니다. 그러면, Ref 객체의 .current 값은 우리가 원하는 DOM 을 가르키게 됩니다.
(출처: https://react.vlpt.us/basic/10-useRef.html)
*useHistory( )
useHistory hook은 화면이동에 사용할 수 있는 history 인스턴스에 접근하게 해준다.
history 객체입니다.
리액트 라우터에서 화면이동을 할 때 항상 history, location, match 라는 객체에 필요한 정보들을 보내게 되어있습니다.
즉, 공식문서에서 말하는 history 인스턴스는 화면이동을 할 때 보내는 history, location, match 중 history에 해당합니다. 여기에 접근하게 해준다는 거죠.
-history 객체
history 객체는 라우트로 사용된 컴포넌트에게 match, location 과 함께 전달되는 props 중 하나입니다. 이 객체를 통하여, 우리가 컴포넌트 내에 구현하는 메소드에서 라우터에 직접 접근을 할 수 있습니다 - 뒤로가기, 특정 경로로 이동, 이탈 방지 등..
(출처:https://react.vlpt.us/react-router/04-extra.html)
CreateWord.js 코드
import {useRef} from "react";
import { useHistory } from "react-router";
import useFetch from "../hooks/useFetch";
export default function CreateWord(){
const days = useFetch("http://localhost:3001/days");
const history = useHistory();
function onSubmit(e){
e.preventDefault();
fetch(`http://localhost:3001/words/`,{//요청의 옵션들 입력
method:'POST',
headers:{//Content-Type 은 보내는 리소스의 타입을 의미
'Content-Type' : 'application/json',
},
body :JSON.stringify({//json 문자열로 반환하기 위해 사용
day : dayRef.current.value,
eng : engRef.current.value,
kor : korRef.current.value,
isDone : false
}),
}).then( res => { //응답 OK 이면 state 를 if 조건문
if(res.ok){
alert('생성이 완료되었습니다.');
history.push(`/day/${dayRef.current.value}`)
}
});
}
const engRef = useRef(null) //scroll위치나 DOM 의 접근 이용할때 사용할 것> useRef
const korRef = useRef(null)
const dayRef = useRef(null)
return (
<form onSubmit={onSubmit}>
<div className="input_area">
<label>Eng</label>
<input type="text" placeholder="computer" ref={engRef}/>
</div>
<div className="input_area">
<label>kor</label>
<input type="text" placeholder="컴퓨터" ref={korRef}/>
</div>
<div className="input_area">
<label>Day</label>
<select ref={dayRef}>
{days.map(day =>(
<option key={day.id} value={day.day}>
{day.day}
</option>
))}
</select>
</div>
<button>저장</button>
{/* DOM 의 결과가 렌더링 반영된 후 저장 버튼 눌려져야함. */}
</form>
);
}
isDone(true/false (외웠는지 안외웠는지 체크하도록)), 영단어, 한글 뜻, 날짜 선택 가능한 value 값들을 가져온다.
CreateDay.js 파일
// import {useRef} from "react";
import { useHistory } from "react-router";
import useFetch from "../hooks/useFetch";
export default function CreateDay(){
const days = useFetch('http://localhost:3001/days');
const history = useHistory();
function addDay(){
fetch(`http://localhost:3001/days/`,{//요청의 옵션들 입력
method:'POST',
headers:{//Content-Type 은 보내는 리소스의 타입을 의미
'Content-Type' : 'application/json',
},
body :JSON.stringify({//json 문자열로 반환하기 위해 사용
day : days.length + 1
}),
}).then( res => { //응답 OK 이면 state 를 if 조건문
if(res.ok){
alert('생성이 완료되었습니다.');
history.push(`/`)
}
});
}
return(
<div>
<h3>현재 일수 : {days.length}일</h3>
<button onClick={addDay}>Day 추가</button>
</div>
);
}
history.push('/') >> 메인페이지로 돌아가는 것. 혹은 그 fetch된 페이지의 날짜 리스트를 보여준다.
페이지에서 실행되는 영상
'front-end > React' 카테고리의 다른 글
[React 입문] useEffect, fetch() 로 API 호출 (0) | 2021.07.01 |
---|---|
[React 입문] 더미 데이터,라우터 구현 (json, react-router-dom) (0) | 2021.06.30 |
리액트 입문 - 설치와 명령어 쳐보고 구조파악 (0) | 2021.05.25 |