Week 1 회고
Day 1 / Emotion 연습
flex 연습을 위한 과제였는데, 내가 어디가 얼마나 부족한지 다시 한 번 알 수 있었던 과제였다.
잘게 잘게 쪼개서 div를 잡고 space-between과 padding 값을 잘 잡아주어야 한다는 것,
border를 잘 이용하면 굳이 line만을 위한 div를 잡지 않아도 된다는 점,
또 어떻게 div를 잡아야 하는지... 멘토님의 리뷰를 들으며 다시 확인할 수 있었다.
React를 처음 접해서 어떻게 사용해야할 지 감이 잡히지 않았었는데 동료의 도움으로 잘 적용시킬 수 있었다.
나에게는 너무 벅찬 과제라고 느끼고 너무 어렵다고 생각해 밤 늦게까지 붙잡고 끙끙댔었는데,
고작 일주일 지난 지금 다시 보니 더 잘 할 수 있겠다는 자신감이 든다.
Day 2 / State 활용
state를 활용한 회원가입 폼 만들기
import { useState } from 'react'
import { Warn,
Wrapper,
Title } from '../../../styles/signup'
export default function SignupStatePage(){
const [email, setEmail] = useState("")
const [emailError, setEmailError] = useState("")
const [password, setPassword] = useState("")
const [passwordCheck, setPasswordCheck] = useState("")
const [passwordError, setPasswordError] = useState("")
function onChangeEmail(event){
console.log(event.target.value)
// event.target => 태그전체 <input type="text" ...
// event.target.value => 우리가 입력한 값 [email protected]
setEmail(event.target.value)
}
function onChangePassword(event){
setPassword(event.target.value)
}
function onChangePasswordCheck(event){
setPasswordCheck(event.target.value)
// setPasswordError(event.target.value !== password)
}
function onClickSignup(){
// 진짜 포장이 잘 됐는지 확인해보기
console.log(email)
console.log(password)
console.log(passwordCheck)
if(email.includes("@") === false){
setEmailError("이메일이 올바르지 않습니다!")
} else {
setEmailError("")
}
if(password !== passwordCheck){
setPasswordError("비밀번호가 일치하지 않습니다!")
} else {
setPasswordError("")
}
}
return (
<Wrapper>
<Title>코드캠프 회원가입</Title>
이메일: <input type="text" onChange={onChangeEmail} /><br />
<Warn>{emailError}</Warn>
비밀번호: <input type="password" onChange={onChangePassword} /><br />
비밀번호 확인: <input type="password" onChange={onChangePasswordCheck} /><br />
<Warn>{passwordError}</Warn>
<button onClick={onClickSignup}>회원가입</button>
</Wrapper>
)
}
useState를 연습해보는 과제였다.
useState와 onChange={}, event함수를 처음 사용해보았는데, 처음이라 생소하고 많이 어려웠다.
함수를 사용해본 건 처음인데다 어디가 어떻게 작동하는지 모르겠어서 많이 버벅이고 힘들어했던 기억이 난다.
역시나 이 날도 동료분께 도움을 청해 구조에 대해 이해해보려는 시간을 가졌다.
도와주신 동료 분께 무한한 감사를 느끼고 있다.. ㅠ ㅠ 정말 감사합니다!
이 과제에는
가입하기 버튼을 누르면 조건문을 활용하여 에러를 검증해 주세요.
⇒ 조건1) 이메일에 @가 없으면 에러입니다.
⇒ 조건2) 비밀번호와 비밀번호확인이 다르면 에러입니다.
⇒ 조건3) 에러가 없는 입력에 해당하는 state는 에러를 제거(빈값으로 변경) 합니다.
발생한 에러를 빨간색으로 입력창 하단에 표기해 주세요.
이런 조건까지 부합하게 만들어야 했는데,
조건3을 어떻게하면 구현해낼 수 있을까? 계속 고민을 했는데..
이것 또한 다른 동료 분의 한 마디로 해결이 됐었다.
아직 다른 분들에 비해 지식도 부족하고 혼자 해결하는 부분에서 어려움을 겪는 것 같다.
하지만 하나씩 이해해갈 때마다 발전함을 느끼고 있다.
Day 3 / GRAPHQL 연습하기
코드캠프에서 제공하는 API를 사용해 mutation과 query를 연습해보았다.
https://canyon-buffer-0c2.notion.site/example-1-GRAPHQL-313289352d1b46c081b6f36a065f053b
https://canyon-buffer-0c2.notion.site/backend03-2-GRAPHQL-723400a0f90949fdacf5479eea00ecac
Day 4 / REST-API, GRAPHQL-API
REST-API 요청하기
import axios from 'axios'
import { useState } from 'react'
export default function RestGetPage(){
const [data, setData] = useState("")
const callRestApi = async () => {
const result = await axios.get("https://koreanjson.com/users")
//get=메서드 endpoint= users
console.log(result)
console.log(result.data.title)
setData(result.data.title)
}
return (
<div>
<div>{data}</div>
<button onClick={callRestApi}>REST-API 요청하기</button>
</div>
)
}
Rest-API 요청하기 버튼을 만들고,이 버튼을 클릭했을 때 https://koreanjson.com/users 라는 Endpoint에 get 방식으로 요청하여 데이터를 받아온다.
GRAPHQL-API 요청하기
//import axios from "axios";
import { useState } from "react";
import { useMutation, gql } from "@apollo/client";
const CREATE_PRODUCT = gql`
mutation createProduct(
$seller: String
$createProductInput: CreateProductInput!
) {
createProduct(seller: $seller, createProductInput: $createProductInput) {
_id
number
message
}
}
`;
export default function GraphqlMutationProduct() {
const [seller, setSeller] = useState("")
const [product, setProduct] = useState("")
const [contents, setMyContents] = useState("")
const [price, setPrice] = useState("")
const [data, setData] = useState("")
const [createProduct] = useMutation(CREATE_PRODUCT);
const onClickSubmit = async () => {
const result = await createProduct({
variables: { seller: seller, createProductInput: {
//객체로 묶어 실행
name: product,
detail: contents,
price: price,
},
},
});
console.log(result);
console.log(result.data.createProduct.message);
setData(result.data.createProduct.message);
};
const onChangeSeller = (event) => {
setSeller(event.target.value)
}
const onChangeProduct = (event) => {
setProduct(event.target.value)
}
const onChangeContents = (event) => {
setMyContents(event.target.value)
}
const onChangePrice = (event) => {
setPrice(Number(event.target.value))
// Number는 숫자만 인식하므로 ParseInt(Int형으로 강제형변환)을 쓸 수도 있음
}
return (
<>
판매자: <input type="text" onChange={onChangeSeller}/>
<br />
상품명: <input type="text" onChange={onChangeProduct}/>
<br />
상품내용: <input type="text" onChange={onChangeContents}/>
<br />
상품가격: <input type="number" onChange={onChangePrice}/>
<br />
<button onClick={onClickSubmit}>상품 등록하기</button>
</>
);
}
작성자, 제목, 내용에 대해서 input 태그와 state를 각각 만들고, 직접 입력 받은 작성자, 제목, 내용으로 mutation을 요청한다.
REST-API는 백엔드 값을 모두 받아오고, GRAPHQL-API는 원하는 값만 골라서 받아올 수 있다는 점에서 GRAPHQL-API가 코드 작성에는 조금 더 까다롭다고 느꼈다.
API서버를 주의깊게 살펴봐야하고, 새롭게 배운 gql, variables, async&await를 복습하는 시간을 가졌다.
GRAPHQL-API에서 price값을 자꾸 받아오지 못하는 에러가 났었는데,
setPrice(event.target.value)를 setPrice(Number(event.target.value))이렇게 바꾸니 해결됐다.
코드리뷰시간에 다른 동료분께서 ParseInt를 사용할 수도 있다고 말씀하셔서 하나 더 배울 수 있었다.
Day 5 / 다이나믹 라우팅 & 데이터 조회
상품 등록 화면 만들기
// import axios from 'axios'
import { useMutation, gql } from "@apollo/client";
import { useRouter } from "next/router";
import { useState } from "react";
const CREATE_PRODUCT = gql`
mutation createProduct($seller: String, $createProductInput: CreateProductInput!) {
createProduct(seller: $seller, createProductInput: $createProductInput) {
_id
number
message
}
}
`;
export default function GraphqlMutationPage() {
const router = useRouter();
const [seller, setSeller] = useState("");
const [name, setName] = useState("");
const [detail, setDetail] = useState("");
const [price, setPrice] = useState("");
const [callApi] = useMutation(CREATE_PRODUCT);
const callGraphqlApi = async () => {
// const result = await axios.get("https://koreanjson.com/posts/1") // rest-api 방식
try {
const result = await callApi({
variables: { seller: seller, createProductInput:{
name: name,
detail : detail,
price : price
} },
}); // graphql-api방식
console.log(result);
console.log(result.data.createProduct.message);
alert("게시글 등록에 성공했어요");
alert("상세 페이지로 이동해 볼까요?");
router.push(
// ↓주소 틀렸었음
`/quiz/05-02/${result.data.createProduct._id}`
);
} catch (error) {
alert(error.message);
}
};
const onChangeSeller = (event) => {
setSeller(event.target.value);
};
const onChangeName = (event) => {
setName(event.target.value);
}
const onChangeDetail = (event) => {
setDetail(event.target.value);
};
const onChangePrice = (event) => {
setPrice(Number(event.target.value));
};
return (
<div>
{/* <div>{data}</div> */}
판매자: <input type="text" onChange={onChangeSeller} /> <br />
상품명: <input type="text" onChange={onChangeName} /> <br />
상품내용: <input type="text" onChange={onChangeDetail} /> <br />
상품가격: <input type="number" onChange={onChangePrice} /> <br />
<button onClick={callGraphqlApi}>상품 등록</button>
</div>
);
}
하루하루 배운 것을 습득하기에 바빠 신경쓰지 못했었는데, 돌아보니 매일의 배움이 조금씩 추가되어 하나의 페이지가 만들어져간다는 느낌이 든다. 신기하다!
5일차에는 try~catch문과 router를 사용해 다른 페이지로 이동할 수 있도록 만들었다.
5일간 배웠던 것 중에 router를 가장 흥미롭게 공부했다. 이제 직접 어떠한 동작을 실행시키고 있다는 실감이 들어서일까..
gql로 원하는 데이터를 가져오고, useMutation으로 상품을 등록, useRouter로 데이터를 push한다.
import { useQuery, gql } from "@apollo/client";
import { useRouter } from "next/router";
const FETCH_PRODUCT = gql`
query fetchProduct($productId: ID) {
fetchProduct(productId: $productId) {
_id
seller
name
detail
price
}
}
`;
export default function DynamicRoutedPage() {
const router = useRouter()
console.log(router)
const { data } = useQuery(FETCH_PRODUCT, { //요청이 날아감(비어있는 상태 undefined)
variables: { productId: router.query.ProductId }
// ↑ gql에서 지정하는 값
})
console.log(data)
return(
<div>
<div>{data?.fetchProduct._id} 게시글에 오신 것을 환영합니다</div>
<div>판매자: {data? data.fetchProduct.seller : "loading..." }</div>
<div>상품명: {data? data.fetchProduct.name : "loading..." }</div>
<div>상품내용: {data? data.fetchProduct.detail : "loading..." }</div>
<div>상품가격: {data? data.fetchProduct.price : "loading..." }</div>
{/* 조건부 렌더링: 데이터가 있으면 뒤에꺼(데이터) 보여줘 없으면 앞에꺼(작성자..) 보여줘 */}
{/* // data && data.fetchBoard.number = data?.fetchBoard.number
Optional-Chaining이라고 한다. */}
</div>
)
}
push한 데이터가 이쪽으로 날아와 페이지를 출력한다.
variables: { productId: router.query.ProductId } 에서 앞의 productId와 뒤의 ProductId가 많이 헷갈렸는데, 앞쪽은 gql에 설정되어 있는 값, ProductId는 내가 설정한 다이나믹 라우팅 폴더의 이름이라는 것을 알았다.
다이나믹 라우팅 폴더 이름에는 반드시 대괄호를 쓸 것!
마지막에 다 알맞게 입력한 것 같은데 라우팅이 안돼서 동료 분께 도움을 청했더니 router.push 경로가 잘못됐다고 알려주셨다.
Week 1 포트폴리오
일주일 간 배운 내용을 토대로, 모든 것을 응용해 게시판 등록 페이지와 상세 페이지를 구현했다.
작성자와 비밀번호, 제목, 내용을 입력하면
alert로 게시물 등록 성공을 알린다.
작성페이지에서 입력한 값을 상세페이지로 가져오는 것에 성공!
나머지는 css부터 만들어 둔 것이라 차근차근 만들어가야한다.
벨로그를 쓰며 아무것도 몰랐던 저번주에 비해 많이 발전했구나 새삼 느끼게 됐다.
어려워도 포기하지말고 매일 잔디도 심고 열심히 하자!
Author And Source
이 문제에 관하여(Week 1 회고), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hhjk00/Week-1-회고저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)