2020.코딩일지
[React]코딩앙마-voca-(Create - POST) 본문
Create - POST (생성)
[단어추가]버튼의 기능구현
// component디렉토리안에 📒CreateWord.js생성
export default function CreateWord() {
return;
}
//📒App.js 상단에 선언 및 경로연결하여 컴포넌트 추가
import CreateWord from "./component/CreateWord";
<Route path="/create_word" element={<CreateWord />} />
//📒Header.js에 (버튼있는곳)???버튼태그가없다?????? 경로연결하기 Link to=""
<Link to="/create_word" className="link">
단어 추가
</Link>
버튼클릭하면 경로 이동하는지 확인
📒CreateWord.js에 단어등록 폼만들기
export default function CreateWord() {
return (
<form>
<div className="input_area">
<label>Eng</label>
<input type="text" placeholder="computer" />
</div>
<div className="input_area">
<label>Kor</label>
<input type="text" placeholder="컴퓨터" />
</div>
<div className="input_area">
<label>Day</label>
<select>
<option>1</option>
<option>2</option>
</select>
</div>
<button>저장</button>
</form>
);
}
하지만 옵션에 하드코딩된 day부분을 useFetch를 이용해보자. (map활용)
//함수 윗부분
const days = useFetch("http://localhost:3001/days");
//함수의 return 아래부분 폼태그를 map으로 수정
<select>
{days.map((el) => (
<option key={el.id} value={el.day}>
{/* map이라서 key하는건데 value는 왜넣는건가? */}
{el.day}
</option>
))}
</select>
import { useRef } from "react";
1️⃣폼태그로 감싸진 저장버튼을 누르면 갱신이되는데, 그 (기본기능)이벤트를 잡아 막아주는 함수
2️⃣돔에 접근할 수 있게 한다. useRef 유즈레프 훅 (예. 스크롤위치확인 및 포커스)
3️⃣아래 폼 각input,select태그에 ref를 연결. 돔요소가 생성된 후 접근할 수 있다.
//저장버튼을 누르는 시점은 렌더링 후 일 것이다 (????)
4️⃣저장버튼아니고 폼에 onSubmit추가
5️⃣current해당요소에접근,value는 인풋에입력된값을 얻을 수 있음.
import { useRef } from "react"; //선언해줘야함
import useFetch from "../hooks/useFetch";
export default function CreateWord() {
const days = useFetch("http://localhost:3001/days");
// 1️⃣폼태그로 감싸진 저장버튼을 누르면 갱신이되는데, 그 (기본기능)이벤트를 잡아 막아주는 함수
function onSubmit(e) {
e.preventDefault();
console.log(engRef.current.value);
console.log(korRef.current.value);
console.log(dayRef.current.value); //5️⃣current해당요소에접근,value는 인풋에입력된값을 얻을 수 있음.
fetch(`http://localhost:3001/words/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
day: dayRef.current.value,
eng: engRef.current.value,
kor: korRef.current.value,
isDone: false,
}),
}).then((res) => {
if (res.ok) {
alert("단어 생성이 완료되었습니다");
}
});
}
//2️⃣돔에 접근할 수 있게 한다. useRef 유즈레프 훅 (예. 스크롤위치확인 및 포커스)
const engRef = useRef(null);
const korRef = useRef(null);
const dayRef = useRef(null); //3️⃣아래 폼 각input,select태그에 ref를 연결. 돔요소가 생성된 후 접근할 수 있다.
//저장버튼을 누르는 시점은 렌더링 후 일 것이다 (????)
return (
<form onSubmit={onSubmit}>
{/* 4️⃣여기 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((el) => (
<option key={el.id} value={el.day}>
{/* map이라서 key하는건데 value는 왜넣는건가? */}
{el.day}
</option>
))}
</select>
</div>
<button>저장</button>
</form>
);
}
-->입력하고 [저장]버튼을 누르면 alert:생성되었다고 안내하고, "수동으로 추가한day에 가보면" 단어 추가되어있음!
그래서 자동으로 해당 day로 이동하게끔 하려고 한다.
react-router의 useHistory() 가 react-router v6에서
resct-router-dom의 useNavigate()로 네이밍 변화되면서 사용법도 살짝 바뀌었으니 확인하자!
구. useHistory()사용법
구. useHistory()사용법
//상단에 선언
import { useHistory}from "react-router";
//함수내 변수에 넣고
const history = useHistory();
//내부함수 내 alert아래에 이동할 주소 추가
history.push(`/day/${dayRef.current.value}`);
//상단에 선언 (선언위치가 달라졌다)
import { useNavigate } from "react-router-dom";
//함수내 변수에 넣고
const navigate = useNavigate();
//내부함수 내 alert아래에 이동할 주소 추가 (push가없다)
navigate(`/day/${dayRef.current.value}`);
새로운경로개척2
[day추가]버튼의 기능구현
// component디렉토리안에 📒CreateDay.js생성
export default function CreateDay() {
return;
}
//📒App.js 상단에 선언 및 경로연결하여 컴포넌트 추가
import CreateDay from "./component/CreateDay;
<Route path="/create_day" element={<CreateDay />} />
//📒Header.js에 (버튼있는곳)???버튼태그가없다?????? 경로연결하기 Link to=""
<Link to="/create_day" className="link">
day 추가
</Link>
📒CreateDay.js의 리턴아래 폼 만들기
export default function CreateDay() {
return (
<div>
<h3>현재 일수 : 10일 </h3>
<button>Day 추가</button>
</div>
);
}
여기도 useFetch로 현등록되어있는 일수를 가져와보자!
import useFetch from "../hooks/useFetch";// 상단에 추가
export default function CreateDay() {
const days = useFetch("http://localhost:3001/days"); //날짜useFetch로가져오기
return (
<div>
<h3>현재 일수 : {days.length}일 </h3> {/* 여기에 적용 */}
<button>Day 추가</button>
</div>
);
}
날짜추가=단어추가(CreateWord)와 같은 로직
버튼에 onClick걸어주고/ 함수생성 POST보내어 날짜를 생성한다./첫페이지로 이동하는 navigate
import { useNavigate } from "react-router";
import useFetch from "../hooks/useFetch"; // 상단에 추가
export default function CreateDay() {
const days = useFetch("http://localhost:3001/days"); //날짜useFetch로가져오기
const navigate = useNavigate();
function addDay() {
//2️⃣함수생성
fetch(`http://localhost:3001/days/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
day: days.length + 1,
}),
}).then((res) => {
if (res.ok) {
alert("날짜 생성이 완료되었습니다");
navigate(`/`); //완료가되면첫페이지로이동 navigate추가 위에도ㅋㅋ
}
});
}
return (
<div>
<h3>현재 일수 : {days.length}일 </h3> {/* 여기에 적용 */}
<button onClick={addDay}>Day 추가</button> {/* 1️⃣onClick걸어주고 */}
</div>
);
}
네트워크에서 느린3G환경으로 테스트하며 Loading...을 추가해주는 섬세함.
📒useFetch.js의 초기값이 `useState([])` 빈배열이므로 길이가0이면 Loding을 보여주자. (판단)
//📒DayList.js의 함수 내에 추가 (처음접속시 뜨는 로딩)
if (days.length === 0) {
return <span>Loading...</span>;
}
//📒Day.js의 리턴아래 추가 (날짜클릭시 뜨는 로딩)
{words.length === 0 && (<span>Loading......</span>)}
//❌단어추가시 저장버튼 여러번 누르는것 모두 받는것..ㅎㄷㄷ (네트워크에서 확인가능)방지하기
//통신중에는 저장버튼이 안먹히게 만들자.
//📒CreateWord.js에서 함수내 state선언
const [isLoading, setIsLoading] = useState(false); //isLoading이 false일때만 작동하라!
😒뉘예? 이해가안갔습니다... 차차보겠습니다..
CreateWord.js의 풀코드
import { useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import useFetch from "../hooks/useFetch";
export default function CreateWord() {
const days = useFetch("http://localhost:3001/days");
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
// 1폼태그로 감싸진 저장버튼을 누르면 갱신이되는데, 그 (기본기능)이벤트를 잡아 막아주는 함수
function onSubmit(e) {
e.preventDefault();
// console.log(engRef.current.value);
// console.log(korRef.current.value);
// console.log(dayRef.current.value); //current해당요소에접근,value는 인풋에입력된값을 얻을 수 있음.
if (!isLoading) {
//2️⃣이걸로 감싸주기
setIsLoading(true); //3️⃣true설정
fetch(`http://localhost:3001/words/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
day: dayRef.current.value,
eng: engRef.current.value,
kor: korRef.current.value,
isDone: false,
}),
}).then((res) => {
if (res.ok) {
alert("단어 생성이 완료되었습니다");
navigate(`/day/${dayRef.current.value}`);
setIsLoading(false); //4️⃣마지막엔 false로바꿔주면된다니...왜????
}
});
}
}
//돔에 접근할 수 있게 한다. useRef 유즈레프 훅 (예. 스크롤위치확인 및 포커스)
const engRef = useRef(null);
const korRef = useRef(null);
const dayRef = useRef(null); //아래 폼 각input,select태그에 ref를 연결. 돔요소가 생성된 후 접근할 수 있다.
//저장버튼을 누르는 시점은 렌더링 후 일 것이다 (????)
return (
<form onSubmit={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((el) => (
<option key={el.id} value={el.day}>
{/* map이라서 key하는건데 value는 왜넣는건가? */}
{el.day}
</option>
))}
</select>
</div>
<button
style={{
opacity: isLoading ? 0.3 : 1,
}}
>
{isLoading ? "Saving..." : "저장"}
</button>
{/* 5️⃣저장버튼에도 삼항연산자넣어주고 살짝흐리게 스타일줌*/}
</form>
);
}
이 파일들을 타입스크립트를 적용해보자(초보)
처음부터 타입스크립트를 적용해서 개발했다면,
오류율도 적고, 에러잡기도 쉬웠을테고, 개발속도도 빨라졌을 것. 이라고 한다.
'JS & React' 카테고리의 다른 글
예시]state끌어올리기(Lifting State Up) 자식의 값을 부모에게 반영-보여줄게완전히달라진값 (0) | 2022.08.01 |
---|---|
예시]state끌어올리기(Lifting State Up) 자식의 값을 부모에게 반영-Twittler React (0) | 2022.08.01 |
[React]코딩앙마-voca-(Update - PUT, Delete - DELETE) (0) | 2022.07.30 |
[React]코딩앙마-voca-(Read - GET)useEffect(),API연결 (0) | 2022.07.30 |
[JS/Node]PART2-Node.js의fs모듈(callback,promise,async) [BEB 6th] (0) | 2022.07.26 |