유저가 데이터 달라고 요청하면 데이터를 보내주는 간단한 프로그램
어떤 데이터인지 (URL 형식으로)
어떤 방법으로 요청할지 (GET or POST)
예를 들어서 쇼미더럭키짱이라는 네이버웹툰을 보고싶으면
https://comic.naver.com/webtoon/list?titleId=783054 여기 URL로 GET요청하면 보내줍니다.
예를 들어서 독립일기라는 네이버웹툰을 보고싶으면
https://comic.naver.com/webtoon/list?titleId=748105 여기 URL로 GET요청하면 보내줍니다.
URL을 어떻게 알았냐고요?
네이버 웹툰 서버개발자에게 물어보거나 URL이 기재된 html 페이지를 찾아보거나 그러면 됩니다.
GET 요청을 하는 가장 쉬운 방법은 브라우저 주소창을 이용하는 것.
POST요청을 날리고 싶으면 <form action='요청할URL' method='post'>
태그 이용하면 됨.
단 이렇게 하면 브라우저가 새로고침 됨.
: 서버에 GET, POST 요청을 할 때 새로고침 없이 데이터를 주고받을 수 있게 도와주는 브라우저 기능.
AJAX로 GET/POST 이용하는 방법
1. XMLHttpRequest(구식 문법)
2. fetch() - 최신 문법
3. axios 외부라이브러리
axios 써보자
npm install anxios
import axios from 'axios'
function App(){
return (
<button onClick={()=>{
axios.get('https://codingapple1.github.io/shop/data2.json').then((결과)=>{
console.log(결과.data)
})
.catch(()=>{
console.log('실패함')
})
}}>버튼</button>
)
}
then/ catch?
.then (GET 성공시 실행 함수)
.catch(실패시 실행 함수)
버튼 누르면 서버에서 받은 데이터를 이용해서 상품 더 보여주기.
let [btnCount, setBtnCount] = useState(0);
//버튼 카운트 스테이트를 만들어주고.
axios.get(
`https://codingapple1.github.io/shop/data${btnCount + 2}.json`
//이렇게 백틱써도 되지만 if esle if로 카운트마다 조건걸어주고
// 각 url을 써줘도 될듯. 근데 url이 많다면?
//그리고 버튼에는 카운트가 증가함에 따라 조건을 걸어두고 disabled되게 함
<button disabled={btnCount === 2 ? true : false}>
axios.post('URL', {name : 'kim'})
이렇게 하면 객체 자료가 전송되고 GET과 마찬가지로 .then()을 이용하여 성공시 실행 코드를 붙일 수도 있다.
Promise.all([axios.get('URL1'), axios.get('url2')])
이것도 .then() 이용 가능.
"{"name" : "kim"}" 이런식으로 obj/arr에 따옴표를 치면 됨.
이를 JSON이라고 함.
JSON은 string 취급을 하기에 서버와 자유롭게 주고 받을 수 있음.
그래서 실제로 결과.data를 출력해보면 따옴표쳐진 JSON이 나오지 않고
obj/arr가 잘 나오는데
axios 라이브러리가 JSON -> obj/arr 변환 작업을 자동으로 적용해줘서 그렇다.
fetch('URL').then(결과 => 결과.json()).then((결과)=>{console.log(결과))
axios 라이브러리를 안쓰고 자바스크립트의 fetch 함수를 사용하면 이렇게 JSON 변환 작업이 필요함. 라이브러리 만세.
내용 div을 만들었고 state도 생성했음.
{탭 === 0 ? <div>내용0</div> : null}
{탭 === 1 ? <div>내용1</div> : null}
{탭 === 2 ? <div>내용2</div> : null}
이런식으로 삼항연산자를 배치해도 되지만 더 좋은 방법 없을까.
function TabContent(){
if (탭 === 0){
<div>내용0</div>
}
if (탭 === 1){
<div>내용1</div>
}
if (탭 === 2){
<div>내용2</div>
}
}
function TabContent({ 탭 }) {
return [<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][탭];
}
function TabContent({ 탭 }) {
let [효과, 효과변경] = useState("");
useEffect(() => {
효과변경("end");
return () => {
효과변경(" ");
}; // 이런식으로 클린업 함수에 먼저 주면 안될까? 했는데
// 리액트의 automatic batching 기능 때문에
//효과변경('') -> 효과변경('end') 이렇게 실행되는게 아니라
// 이전 변경 스테이트는 무시하고 최종 변경스테이트함수를 기준으로만 재렌더링 함.
}, [탭]);
return (
<div className={"start " + 효과}>
{[<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][탭]}
</div>
);
}
---------
useEffect(() => {
setTimeout(() => {
효과변경("end");
}, 100);
return () => {
효과변경(" ");
}; //이런식으로 텀을 두고 실행해주면 된다.
let [state, setState] = useState("");
useEffect(() => {
setState("end");
return () => {
setState(" ");
};
}, []); //컴포넌트 마운트때 end붙이고 unmount때 ''으로 실행.
<div className={"container start " + state}>
좀 더 정확히 useEffect에 대해 공부하고 따로 정리하는 글 남겨봐야겠음.
props는 부모 -> 자식만 가능하다.
부모 -> 자식 - > 자식도 가능함
근데 이거 귀찮다.
뭔가 방법이 없을까?
(App.js)
export let context = createContext();
// state 보관함, 다른 컴포에서도 사용가능하게 export
function App(){
let [재고, 재고변경] = useState([10,11,12]);
let [shoes, setShoes] = useState(data);
return (
<Context1.Provider value={ {재고,shoes (원하는 state 넣기)} }>
<Detail shoes={shoes}/>
</Context1.Provider>
// Context로 감싼 모든 컴포넌트와 그 컴포넌트의 자식들은
// value에 할당해준 state들을 props 전송 없이 사용할 수 있다.
)
}
import {useState, useEffect, useContext} from 'react';
import {Context1} from './../App.js';
function Detail(){
let {재고, shoes} = useContext(Context1)
// destructuring 으로 할당해도 되고
let a = useContext(Context1)
//이런식으로 변수에 할당해서 사용해도 된다.
return (
<div>{재고}</div>
)
}
Detail 컴포의 자식 컴포에서도 useContext 할당해주고 사용해보면 잘 나온다.
console.log(shoes[0], 재고[0]);
//이벤트 함수 내에 위치시키고 찍어보면 잘 나옴.