2차 공부/TIL

24.09.27 넥스트에서 tanstackquery 사용하기

공대탈출 2024. 9. 27. 01:01
// /stores/queryProvider.tsx
"use client";

import { isServer, QueryClient, QueryClientProvider } from "@tanstack/react-query";

function makeQueryClient() {
    return new QueryClient({
        defaultOptions: {
            queries: {
                staleTime: 60 * 1000,
            },
        },
    });
}

let browserQueryClient: QueryClient | undefined = undefined;

function getQueryClient() {
    if (isServer) {
        return makeQueryClient();
    } else {
        if (!browserQueryClient) browserQueryClient = makeQueryClient();
        return browserQueryClient;
    }
}

export default function Providers({ children }: { children: React.ReactNode }) {
    const queryClient = getQueryClient();

    return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}

먼저 세팅을 해주자. 위 코드는 넥스트에서 제공해주는 세팅 코드이다.

그렇게 만들어진 Provider을 root layout에서 감싸준다.

 

import type { Metadata } from "next";
import "./globals.css";
import Providers from "./stores/queryProvider";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import Link from "next/link";

export const metadata: Metadata = {
    title: "Create Next App",
    description: "Generated by create next app",
};

export default function RootLayout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <html lang="en">
            <body>
                <header>
                	//...
                </header>
                <Providers>
                    <ReactQueryDevtools />
                    {children}
                </Providers>
            </body>
        </html>
    );
}

이렇게 root layout에서 감싸주면 된다.

"use client";

import { getTodosSSR } from "@/server-action";
import { useQuery } from "@tanstack/react-query";
import React from "react";

const NormalFetchTodosPage = () => {
    const { data: todos } = useQuery({
        queryKey: ["normalFetchedTodos"],
        queryFn: () => {
            console.log("isnt preFetched");
            return getTodosSSR();
        },
        staleTime: 1000,
    });

    return (
        <div>
            <h1>Normal Todos Page</h1>
            <ul>
                {todos?.map((todo) => {
                    return <li key={todo.id}>{todo.title}</li>;
                })}
            </ul>
        </div>
    );
};

export default NormalFetchTodosPage;

그리고 어떤 컴포넌트에서 useQuery를 잘 사용할 수 있다.

 

prefetch를 사용하려면

import PrefetchedTodos from "@/components/PrefetchedTodos";
import { getTodos } from "@/server-action";
import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query";
import React from "react";

const PrefetchPage = async () => {
    const queryClient = new QueryClient({
        defaultOptions: {
            queries: {
                staleTime: 1000 * 60 * 10,
            },
        },
    });
    await queryClient.prefetchQuery({
        queryKey: ["prefetchedTodos"],
        queryFn: () => {
            console.log("prefetched!");
            return getTodos();
        },
    });
    return (
        <HydrationBoundary state={dehydrate(queryClient)}>
            <PrefetchedTodos />
        </HydrationBoundary>
    );
};

export default PrefetchPage;
"use client";
import { Todo } from "@/server-action";
import { useQuery } from "@tanstack/react-query";
import React from "react";

const PrefetchedTodos = () => {
    const {
        data: todos,
        isLoading,
        isError,
    } = useQuery({
        queryKey: ["prefetchedTodos"],
        queryFn: async () => {
            console.log("isPrefetched?");
            const res = await fetch("http://localhost:4000/todos");
            const data: Todo[] = await res.json();
            return data;
        },
        staleTime: 1000 * 60 * 10,
    });

    if (isLoading) return <>Loading...</>;
    if (isError) return <>error</>;

    return (
        <div>
            <h1>Prefetched Todos Page</h1>
            <ul>
                {todos?.map((todo) => {
                    return <li key={todo.id}>{todo.title}</li>;
                })}
            </ul>
        </div>
    );
};

export default PrefetchedTodos;

이렇게 미리 fetch해놔서 사용자경험을 증가시킬 수 있다.

 

'2차 공부 > TIL' 카테고리의 다른 글

24.10.01 트러블 슈팅  (1) 2024.10.02
24.09.30 트러블 슈팅  (0) 2024.10.02
24.09.25 nextjs의 4가지 주요 렌더링 기법  (0) 2024.09.25
24.09.23 팀프로젝트 마무리  (2) 2024.09.23
24.09.20 팀프로젝트 진행상황  (1) 2024.09.20