s e o p p o r t . l o g

Today I Learned

Next.js와 tanstack Query를 이용한 서버 통신 처리

Seo Ji Won 2024. 3. 14. 18:09

 

1. queryProvider 생성 및 RootLayout에 적용

'use client';
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const QueryProvider = ({ children }: React.PropsWithChildren) => {
  const queryClient = new QueryClient();

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

export default QueryProvider;
//RootLayout

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang='en'>
      <QueryProvider>
        <body className={inter.className}>
          <NavBar />
          {children}
        </body>
      </QueryProvider>
    </html>
  );
}


2. route 백엔드 api 준비(선택)

//api > todos > route.ts
//GET, POST 등등..
export async function POST(request: Request) {
  // 들어온 데이터를 js 객체로 파싱
  const { title, contents }: { title: Todo['title']; contents: Todo['contents'] } = await request.json();

  const response = await fetch('http://localhost:4000/todos', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },

    //다시 json화해서 서버 통신
    body: JSON.stringify({ title, contents, isDone: false }),
  });

  const todo = await response.json();

  if (!todo) {
    return (
      new Response('todo is not found'),
      {
        status: 404,
      }
    );
  }

  return Response.json({ todo, message: '추가되었습니다.' });
}

 

3. 클라이언트에서 fetch하는 함수 생성

// src/hooks/fetchTodo.ts
export const addTodo = async ({ title, contents }: { title: Todo['title']; contents: Todo['contents'] }) => {
  const response = await fetch('http://localhost:3000/api/todos', {
    method: 'POST',
    body: JSON.stringify({ title, contents }),
  });

  if (!response.ok) {
    throw new Error('Failed to add todo item ');
  }

  const result = await response.json();
  alert(result.message);
};


4. mutate 커스텀 훅 생성

// src/hooks/mutateTodos.tx
export const useAddTodoMutation = () => {
  const queryClient = useQueryClient();

  const addMutation = useMutation({
    mutationFn: addTodo,
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: [QueryKeys.TODOS],
      });
    },
  });

  return addMutation;
};

 


5. 컴포넌트에서 mutate import하여 사용

mutate함수에 서버에 전달할 값을 넣어주면 된다.

// 컴포넌트
 const addMutation = useAddTodoMutation();
 addMutation.mutate({ title, contents: content });

 

실행 순서

addMutation.mutate가 값을 갖고 addMutation훅으로 이동 

>  addMutation 에서 mutationFn에 지정한 addTodo 훅으로 이동

> addTodo의 POST 요청이 api/toods/route의 백엔드 api를 거쳐 서버와 통신