propsdrilling => Redux => Recoil, contextAPI => Zustand /// ReactQuery( 결이 다름)
기존 Redux = 서버 DB에 수정해달라 하고, 리덕스 store 에 수정하고 해야함. 서버와 맞추면서 바꾸는게 너무 불편...ㅜ
=> 서버 DB와 동기화 시켜 주기 위해 React Query 를 사용.
모달창, 팝업창이 떠있는지 안떠있는지, 사용자가 어떤 페이지에서 뭐하는지 (클라이언트에서 관리하는거) => Redux , ContextAPI
나머지 서버 사이드 => React Query
홈페이지가 어딘지 잘 모르겠어 => () 소괄호 사용해서 관리.
설치
npm i @tanstack/react-query
//dev tools
npm i @tanstack/react-query-devtools
사용방법?
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
const queryClient = new QueryClient();
export function ReactQueryProvider({
children,
}: {
children: React.ReactNode;
}) {
return (
<QueryClientProvider client={queryClient}>
{children}
<ReactQueryDevtools />
</QueryClientProvider>
);
}
// 실제 예제
const getAllSuperHero = async () => {
return await axios.get("http://localhost:4000/superheroes");
};
const { data, isLoading } = useQuery({
queryKey: ["super-heroes"],
queryFn: getAllSuperHero,
});
// An individual todo
useQuery({ queryKey: ['todo', 5], ... })
// An individual todo in a "preview" format
useQuery({ queryKey: ['todo', 5, { preview: true }], ...})
// (2) 상단의 queryKey 예제와 반대로 queryFn 자체적으로 인자를 받는 형태
const getSuperHero = async (heroId: string) => {
return await axios.get(`http://localhost:4000/superheroes/${heroId}`);
};
const useSuperHeroData = (heroId: string) => {
return useQuery({
queryKey: ["super-hero", heroId],
queryFn: () => getSuperHero(heroId), // (*)
});
};
const useSuperHeroData = (heroId: string) => {
return useQuery({
queryKey: ["super-hero", heroId],
queryFn: () => getSuperHero(heroId),
gcTime: 5 * 60 * 1000, // 5분
staleTime: 1 * 60 * 1000, // 1분
retry: 1,
// ... options
});
};
R(read)는 useQuery, CUD(Create, Update, Delete)는 useMutation을 사용한다.
컴포넌트 레벨에서만 사용할 수 있어. (use... 등 훅 쓰는 자리에서.). 예를 들면, useEffect(), submit() 안에서 못씀
const mutation = useMutation({
mutationFn: createTodo,
onMutate() {
/* ... */
},
onSuccess(data) {
console.log(data);
},
onError(err) {
console.log(err);
},
onSettled() {
/* ... */
},
});
const onCreateTodo = (e) => {
e.preventDefault();
mutate({ title });
};
use Mutation 은 mutationFn 만 받음
useMutation의 반환 값인 mutation 객체의 mutate 메서드를 이용해서 요청 함수를 호출할 수 있다.
mutate는 onSuccess, onError 메서드를 통해 성공 했을 시, 실패 했을 시 response 데이터를 핸들링할 수 있다.
onMutate는 mutation 함수가 실행되기 전에 실행되고, mutation 함수가 받을 동일한 변수가 전달된다.
onSettled는 try...catch...finally 구문의 finally처럼 요청이 성공하든 에러가 발생되든 상관없이 마지막에 실행된다.
뒤는 강의 정리
useQuery({ queryKey: ["til", { category: "latest" ,sort: "",}] });
required 로 한개를 일단 만듬.(객체로 만들기 때문에 다양하게 가능).
첫번째에는 queryKey: [] (배열로 쓴다)
정체 identity가 될 명사를 적어놓는다. 두번쨰에는 다양한 정보를 적는다.
사용된 쿼리에 대한 쿼리 키가 다 캐시에 정장돼
useQuery(queryKey:[],
queryFn : API.~~~}
);
useQuery 안에 들어있는 것 중 중요한것들
상세페이지 만들때는 대괄호로 디렉토리 만들어 => params 처럼
params는 항상 string
function TilDetailPage(props: {params: {tilId:string}})
useQuery({queryKey: ["til", {id:tilId}], queryFn: async () => {}})
엑세스 토큰

JSON 웹 토큰은 디코드가 된다. 내용까면 다나와 => 암호화와 관련이 없음
iat: 언제 발급되었는지
sub: 아이디
name: 이름
로그인 보장이 안될때
useEffect(() => {
if (isLoggedIn) {
router.replace("/");
}
}, [router, isLoggedIn]);
이렇게 바뀐게 보장이 될때!