2020.코딩일지

[React]코딩앙마-voca-(Create - POST) 본문

JS & React

[React]코딩앙마-voca-(Create - POST)

개발하는라푼젤 2022. 7. 30. 19:40
728x90

     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>
  );
}

day추가버튼 눌렀을때 나오는 화면

여기도 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>
  );
}

 

 


이 파일들을 타입스크립트를 적용해보자(초보)

처음부터 타입스크립트를 적용해서 개발했다면, 

오류율도 적고, 에러잡기도 쉬웠을테고, 개발속도도 빨라졌을 것. 이라고 한다. 

https://youtu.be/g-kauNOTVRY

 

Comments