1주차
동기와 비동기를 구분하는 개념 : 순차적이냐 비순차적이냐
요청과 응답이 순차적으로 일어나는 방식
요청을 보냐면 그 응답이 올 때까지 대기한 후 작업 진행
위에서 아래로 쭉
일의 순서가 중요한 경우 동기처리
ex) 기상청에서 날씨 데이터를 json형식으로 통신하여 받아온 후, 해당 내용을 브라우저 상에 react컴포넌트로 반환해야할 경우
비효율적일 수 있다.
비동기는 비순차적, 요청을 보내고 응답을 기다리지 않고
일의 순서가 중요하지 않은 경우 효율적인 일 처리를 위해 비동기 처리함
요청을 보낸 상태에서 완료를 기다리지 않고 바로 밑에 것을 수행한다.
예제코드
function sendTextMessage(message, callback) {
// 메시지를 보내는 비동기 작업을 가정해요.
setTimeout(() => {
console.log("문자 메시지 전송 완료: " + message);
callback(); // 응답이 도착하면 콜백 함수 호출
}, 2000); // 2초 후에 메시지 전송이 완료된다고 가정
}
console.log("메시지 보내기 시작");
sendTextMessage("안녕, 잘 지내?", function () {
console.log("메시지 전송 후 후속 작업 수행");
});
console.log("다른 작업 수행");
// 출력 결과:
// 메시지 보내기 시작
// 다른 작업 수행
// 문자 메시지 전송 완료: 안녕, 잘 지내?
// 메시지 전송 후 후속 작업 수행
for문은 기본적으로 동기적으로 실행된다.
useEffrct fetch는 외부에 있는 데이터를 가져오기 떄문에 비동기적이다.
이를 처리하기 위해서 .then을 이용한다.
promise
비동기 작업의 완료 혹은 실패를 처리하기 위해 사용되는 개념이다.
Promise객체를 생성하기 위해 Promise생성자를 사용할 수 있다.
//콜백함수를 중첩해서 사용하면 콜백지옥이 발생해서 이를 해결하기 위해 나옴
Promise는 3가지 상태를 가진다.
대기(Pending)는 초기상태로 promise요청을 날렸을 때 resolve나 reject로 인해 다른 상태로 변경되기 전까지의 상태
이행(fulfilled)은 비동기 작업이 성공적으로 완료된 상태
거부는(rejected) 비동기 작업이 실패한 상태
tnen(완료됐을 때), catch(실패했을 때), finally(어떤 상태이든지 무조건) 메서드를 통해 이행되거나 거부된 이후의 동작을 정의할 수 있다.
Promise 생성방법
const newPromise = new Promise((resolve (성공), reject(실패)) =>
{로직 if (성공) {resolve(뫄뫄뫄)} elae {reject(작업실패)}}, 1000(1초후 작업완료))
newPromise
.tnen((result) => {뫄뫄뫄 출력})
.catch((error) => {작업실패 출력})
fetch 함수는 promise 객체를 반환한다.
그래서 fetch함수를 사용할 때 then이나 catch를 사용하는 것이다.
여러 비동기 작업을 병렬로 처리하기
순서는 상관없는 1,2,3을 처리하고 그 다음 작업을 수행해야할 때 병렬로 처리할 수 있다.
더 공부해야할 개념들
콜백함수
useEffect
useState
reRendering
1-2주차
jsonserver = fake server
supabase처럼 각각의 서버임.
react서버와 json서버는 달라서 통신을 해야하는데 그러려면 fetch,,, 변환을 해줘야 했는데, 이 귀찮은 걸 해결하는 게 axios이다.
데이터 가져와서 전역으로 사용하기 : useContext
TanStack Query는 fetch + useContext라고 생각하면 된다.
별도로 데이터를 늘리는 로직을 사용하지 않아도 된다. 캐시 컨텍스트 내부적으로 useContext를 사용
1. jsonserver
2. axios
axios사용이유
1. 요청/응답 시 json 데이터 형식을 기본으로 한다.
즉, .json을 자동으로 해준다. fetch는 .json을 호출해 수동으로 파싱해야하는 것을 axios에서 해주는 것이다.
여기서 json파싱은 서버에서 받은 데이터는 텍스트 형식으로 전달되는데, 이 텍스트를 자바스크립트가 이해할 수 있는 객체 형식으로 변환하는 것을 의미한다.
요약 : json에서 가져온 텍스트를 컴퓨터가 이해할 수 있게 변환 하는 것. (파싱==변환)
2. GET요청
1. URL
2. Method
1) GET : 데이터 조회
2) POST : 데이터 생성
3) PUT : 데이터 전체 수정
4) PATCH : 데이터 일부 수정
5) DELETE : 데이터 삭제
ex) .get ('http://~~~') get은 메서드, 그 뒤는 url
3. POST요청
뭘 입력할거야
post와 patch는 body가 있다.
Authorization : 이 토큰(accessToken)을 가지고 있는 사람만 접근할 수 있다. 즉 로그인이 돼있어야만 이 토큰을 가질 수 있다.
yarn add json-server
db.json에 데이터 넣기 (모든 데이터 형식이 json형식으로 되있기 떄문에 json임)
yarn json-server db.json --port 포트번호
실행하면 Endpoints가 뜨는데, 이건 들어갈 수 있는 주소들을 의미한다.
그리고 thunder Cliant를 설치 후 열면 된다.
데이터를 넣을 때 따옴표를 key에 붙이는데, 그건 json이라 넣는 것이다.
put과 patch의 차이 : put은 덮어쓰기, patch는 업데이트이다.
+)delete는 body가 필요없다.
react서버와 axios서버는 별도로 돌려줘야한다.
useEffext에서 []이 부분에 아무것도 안 들어가면 최초 한 번만 실행한다는 뜻이다.
데이터 불러올 때 useEffext 사용
사용법 : axios.get("서버주소")
여기서 강의와 같이 posts뒤에 ?(옵셔널체이닝)을 쓰지 않아도 되는 이유는 state 초기 값이 배열이기 때문입니다!!
빈배열이 아니면 오류가 난다.
const [post, setPosts] = useState([]);
3. TanStack Query
yarn add @tanstack/react-query @tanstack/react-query-devtools 설치
query Client -> 모든 요청을 대신해줄 녀석, TanStack Query의 모든 요청을 해줌.
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
<APP/>
</QueryClientProvider>
app 하위에서 queryClient에서 작업한 모든 것을 이용할 수 있다는 뜻
사용법
const fetchData = async() => {
const {data} = await axios.get('http://~~');
return data;
}
const response = useQuery({
queryKey: [배열로 지정(무조건)],
queryFn: fetchData,
//외부로부터 데이터를 가져올 함수 적으면 된다.
}
});
ispending : 처음에 데이터를 가져올 때는 true, 이후에는 false
const {isLoading, isError, data} = useQuery({
queryKey: [배열로 지정(무조건)],
queryFn: fetchData,
//외부로부터 데이터를 가져올 함수 적으면 된다.
}
});
if (isLoading) {
return <div>로딩중입니다...!</div>;
}
if (isError) {
return <div>오류가 발생하였습니다...!!</div>;
}
isLoading, isError라는 상태를 만들 필요가 없어졌어요. 그냥 가져와서 가져다 사용하면 되죠! 내부적으로 다 처리를 해주는 거예요.
Tanstack Query는 데이터를 페칭해주는 라이브러리가 아니다. 서버(비동기) 상태 관리자. 데이터 페칭은 axios가 해주고 있음.
위에 방법은 데이터를 불러오는 것이었는데, 여기서 데이터를 추가하기 위해서는
const addPost = async(newPost) => {
await axios.get('http://~~',{
title: newPost.title,
views: newPost.views,
})
}
post는 body가 들어가야한다.
useMutation?
useQuery로 데이터 가져옴
useMutation으로 데이터 추가
그리고 가져온 데이터를 무효화를 해줘야한다. 최신 데이터로 반영을 해줘야함
이건 inValidateQuery로 할 수 있다. 얘도 마찬가지로 쿼리 클라이언트가 필요하다. 이미 불러왔으면 또 생성할 필요 없다.
사용법 :
const queryClient = useQueryClient();
useMutation 함수 안에 onSuccess를 넣어서 정보 추가가 완료될 시 실행되는 함수를 넣어준다.
queryClient.inValidateQueries(["posts"])로
심화 1-10, 11
실습
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';
import { useState } from 'react';
const App = () => {
const getPosts = async () => {
const response = await axios.get('http://localhost:4000/posts');
return response.data;
};
const queryclient = useQueryClient();
const [title, setTitle] = useState("");
const [view, setView] = useState(0);
const newPost = (newData) => {
axios.post('http://localhost:4000/posts', {
title: newData.title,
view: newData.view,
});
}
const mutation = useMutation({
mutationFn: newPost,
onSuccess: () => {queryclient.invalidateQueries(['posts']);} //여기 틀림
})
const { data, isLoading, isError } = useQuery({
queryKey: ['posts'],
queryFn: getPosts,
});
if (isLoading) {
return <div>로딩중입니다..</div>;
}
if (isError) {
return <div>오류가 발생했습니다..</div>;
}
return (
<div>
<input value={title} onChange={(e => { setTitle(e.target.value) })} /> {/*여기 틀림*/}
<input value={view} onChange={(e => { setView(e.target.value);})} /> {/*여기 틀림*/}
<button
onClick={() => {
mutation.mutate({
title: title,
view: view,
});
}}
>
제출
</button>
{data.map((post) => {
return <div key={post.id}>{post.title}</div>;
})}
</div>
);
};
export default App;
2주차
mutation 안에 mutate가 들어잇다
코드를 여러 번 사용하는 대신 axios분리, mutation, useQuery분리해주기
api분리
base.js
const baseInstance = axios.create({
baseURl: "http://locahost:4000"
});
export default baseInstance;
이렇게 선언해주면
main.js
const response = await axios.get("http~~")대신에
import baseInstance from~~~
const response = await baseInstance("/posts");를 사용할 수 있다.
커스텀instance
컴포넌트는 한 눈에 파악할 수 있어야 한다.
hooks폴더를 만들어서 queries.jsx, mutation.jsx 파일을 만들어서 안에 문단들을 넣어준다.
queries는
export const usePosts = () =>
useQuery({
queryKey: ["Posts"],
queryFn: getPosts,
})
이후 본문 파일에서
const{data, isLoading, isError} = usePosts();로 사용할 수 있다.
mutation은
(사진)
queryKey도 따로 뺄 수 있다.
export const QUERY_KEYS = {
POSTS: "posts",
}
후 QUERY_KEYS.POSTS로 호출할 수 있다.
3주차
https://github.com/za0012/timeattack3
'부트캠프 > React 심화' 카테고리의 다른 글
React 심화주차 팀 프로젝트 3차시 ? (0) | 2024.09.20 |
---|---|
React 심화주차 개인프로젝트를 진행하며 일어난 트러블 슈팅 (0) | 2024.09.11 |