11.0 Product Model
hot reloading을 하면 일종의 서버 재시작이 돼서
PrismaClient가 계속 new로 생성됨.
DB에 커넥션 리밋이 있음. Planet Scale에 리밋이 있을 것이다.
좋지 않은 것이니. 고쳐

항상 다음 순으로 한다.
Model 생성 -> data base 수정 -> mutation -> 데이터 가져오기

Model 생성

model Product {
  id          Int      @id @default(autoincrement())
  created     DateTime @default(now())
  updated     DateTime @updatedAt
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId      Int
  image       String
  name        String
  price       Int
  description String   @db.MediumText

  @@index([userId])
}

 

11.1 Upload Form
11.2 Upload API

  const { name, price, description } = req.body;
  const { user } = req.session;
  // vs
  const {
    body: { name, price, description },
    session: { user },
  } = req;


Prisma client(back end)의 type을 갖다 쓸 수있다.

 

11.3 See Products
프로덕트에서 상품 정보와 상품등록한 계정의 정보 선택적으로 가져오기.

async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseType>
) {
  console.log(req.query);
  const { id } = req.query;
  const product = await client.product.findUnique({
    where: {
      id: Number(id),
    },
    include: {
      user: {
        select: {
          id: true,
          name: true,
          avatar: true,
        },
      },
    },
  });
  res.json({ ok: true, product });
}

UI: skeleton 로딩화면 tailwind css로 만드는 법
https://www.section.io/engineering-education/skeleton-loading-in-nextjs-with-tailwindcss/

11.4 Product Detail
11.5 Related products

interface extends 해서 type만들기

prisma client의 search 조건
https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#filter-conditions-and-operators

Docs에 있는 것을 아래처럼 구현

 

 

11.6 Favorite Products

import { NextApiRequest, NextApiResponse } from "next";
import withHandler, { ResponseType } from "@libs/server/withHandler";
import client from "@libs/server/client";
import { withApiSession } from "@libs/server/withSession";

async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseType>
) {
  const {
    query: { id },
    session: { user },
  } = req;
  const alreadyExists = await client.fav.findFirst({
    where: {
      productId: Number(id),
      userId: user?.id,
    },
  });
  if (alreadyExists) {
    await client.fav.delete({
      //delete하려면 unique 필드가 필요함
      where: {
        id: alreadyExists.id,
      },
    });
  } else {
    await client.fav.create({
      data: {
        user: {
          connect: {
            id: Number(user?.id),
          },
        },
        product: {
          connect: {
            id: Number(id),
          },
        },
      },
    });
  }
  res.json({ ok: true });
}
export default withApiSession(
  withHandler({
    methods: ["POST"],
    handler,
  })
);


11.7 Favorite Products part Two
Optimistic UI Update - 어차피 API성공할테니 응답 기다리지 말고 일단 UI바꾸기

  const [toggleFav] = useMutation(`/api/products/${router.query.id}/fav`);
  const onFavClick = () => {
    toggleFav({});
  };

toggleFav({})는 POST니까 바디 보내야 하지만 empty 바디 보내도 됨.


11.8 Bound Mutations

useSWR로 data와 mutate를 받을 수 있다.
mutate()의 처음 인자는 변경할 데이터, 두번째 인자는 해당 API를 재 호출 할지 선택하는 옵션이다. default는 true.
첫번째 mutate함수 처럼 사용하면, 기존의 swr 캐에 저장된 data가 인자 {product:{name:"potato"}}로 치환 되기 때문에 화면에 potato 관련 정보만 보이고 나머지는 다 날아가버린다.
그래서 두번 째 mutate처럼 써야한다.
원래 data를 전개해서 넣고, product안을 수정하는데 product에서도 나머지는 전개해서 넣고, name만 바꾼다.

이건 그냥 자바스크립트 문법.

다음 처럼 하면 favorite이 Optimistic UI Update 되는거야.
캐시만 변경하는거지.
mutate({ ...data, isLiked: !data.isLiked }, false);

두번째 인자가 false니까 다시 api 불러오지 않게
그리고 주석처리 된 toggleFave({})도 주석풀어야 실제 API콜이 될테니까.
최종본

그럼 왜 bound냐? 왜 bound mutation이냐?
useSWR로 받아온 mutate와 짝지어진 데이터만 변경 가능해서.
다른 request로 받은 놈의 cache도 바꾸고싶다?
다른 화면의 다른 요청의 cache를 바꾸고싶다?
unbound mutation !!

11.9 Unound Mutations

import useSWR, { useSWRConfig } from "swr";
const { mutate } = useSWRConfig();
mutate("/api/users/me", (prev) => prev && { ok: !prev.ok }, false);
//prev -> 현재 caching된 데이터 가져오기. 어디서든 접근 가능.
mutate("/api/users/me") //이렇게 하면 그냥 업데이트

 

'클론코딩-캐럿마켓 > 전반' 카테고리의 다른 글

13 Profile  (0) 2023.01.09
12 동네생활  (0) 2023.01.06
10 AUTHORIZATION - SWR  (0) 2023.01.04
9 AUTHENTICATION  (0) 2022.12.27
8 REFACTORING  (0) 2022.12.27

+ Recent posts