가수면

[Sanity] CRUD 본문

React/라이브러리

[Sanity] CRUD

니비앙 2023. 6. 29. 11:25

https://www.sanity.io/docs/connect-your-content-to-next-js

https://www.sanity.io/docs/js-client#multiple-mutations-in-a-transaction

 

JavaScript

Our JavaScript API client library

www.sanity.io

그냥 진행하는 방식과 라이브러리 설치해 사용하는 방법이 있는데, 이번 글에선 라이브러리를 이용한 방법을 적는다.

 

npm install @sanity/client

 

기본 설정

각 키는 아래에서 확인 가능함 (토큰은 생성할 때 확인 가능함)

https://www.sanity.io/manage

 

https://www.sanity.io/manage

 

www.sanity.io

export const client = createClient({
  projectId: process.env.SANITY_PROJECT_ID,
  dataset: process.env.SANITY_DATASET,
  useCdn: false, // 동적인 데이터가 주가 된다면 cdn 끄면 됨
  apiVersion: "2023-03-20", // sanity 최신 API를 사용하기 위해 현재 날짜를 입력
  token: process.env.SANITY_SECRET_TOKEN, // 데이터 읽기만 할 거면 사용 안 해도 되지만 수정할 거면 설정해야 함
});

기본 형태

export async function getPosts() {
  const posts = await client.fetch('*[_type == "post"]')
  return posts
}

export async function createPost(post: Post) {
  const result = client.create(post)
  return result
}

export async function updateDocumentTitle(_id, title) {
  const result = client.patch(_id).set({title})
  return result
}

생성

배열에 추가

export async function addComment(
  postId: string,
  userId: string,
  comment: string
) {
  return client
    .patch(postId) // 데이터 id
    .setIfMissing({ comments: [] }) // likes가 undefined라면 초기값 설정
    .append('comments', [ // likes에 추가
      {
        comment,
        author: { _ref: userId, _type: 'reference' },
      },
    ])
    .commit({ autoGenerateArrayKeys: true }); // 데이터 추가할 때 key 자동 설정 옵션
}

이미지 업로드

https://www.sanity.io/docs/assets

next 12버전

next 13버전

12버전에서는 node 환경에서 동작해 node 타입을 사용할 수 있었지만, 13버전에서는 edge에서도 동작할 수 있게 만들어야 해서 node타입을 사용할 수 없음

app폴더의 api 라우트 핸들러에서 client를 사용하면 현재까진 에러가 발생함. sanity에서 고칠 때까지 아래 방식으로 POST 요청을 직접 사용해야 함.

예시)

url 형식

  'https://myProjectId.api.sanity.io/v2021-03-25/assets/images/myDataset'
export async function createPost(userId: string, text: string, file: Blob) {
  return fetch(assetsURL, {
    method: 'POST',
    headers: {
      'content-type': file.type,
      authorization: `Bearer ${process.env.SANITY_SECRET_TOKEN}`,
    },
    body: file,
  })
    .then((res) => res.json())
    .then((result) => {
      return client.create(
        {
          _type: 'post',
          author: { _ref: userId },
          photo: { asset: { _ref: result.document._id } },
          comments: [
            {
              comment: text,
              author: { _ref: userId, _type: 'reference' },
            },
          ],
          likes: [],
        },
        { autoGenerateArrayKeys: true }
      );
    });
}


회원가입 유저 추가

데이터에 추가할 때 중복되는 데이터가 있다면 추가 안 되도록 하는 로직이 필요함 (createIfNotExists)

export async function addUser({ id, username, email, name, image }: User) {
  return client.createIfNotExists({
    _id: id,
    _type: "user",
    username,
    email,
    name,
    image,
    following: [],
    followers: [],
    bookmarks: [],
  });
}

읽기

GROQ

sanity의 오픈 소스 쿼리 언어. 원하는 정보를 groq를 이용해 client에 fetch를 날린다.

https://www.sanity.io/docs/query-cheat-sheet

 

GROQ Query Cheat Sheet - Sort, Filter & Array Examples

Data query examples.

www.sanity.io

export async function getPost(id: string) {
  return client
    .fetch(
      `*[_type == "post" && _id == "${id}"][0]{
      ...,
      "username": author->username,
      "userImage": author->image,
      "image": photo,
      "likes": likes[]->username,
      comments[]{comment, "username": author->username, "image": author->image},
      "id":_id,
      "createdAt":_creatdAt
    }`
    )
    .then((post) => ({ ...post, image: urlFor(post.image) }));
}

수정

export async function addComment(
  postId: string,
  userId: string,
  comment: string
) {
  return client
    .patch(postId) // 데이터 id
    .setIfMissing({ comments: [] }) // likes가 undefined라면 초기값 설정
    .append('comments', [ // likes에 추가
      {
        comment,
        author: { _ref: userId, _type: 'reference' },
      },
    ])
    .commit({ autoGenerateArrayKeys: true }); // 데이터 추가할 때 key 자동 설정 옵션
}

삭제

export async function dislikePost(postId: string, userId: string) {
  return client
    .patch(postId)
    .unset([`likes[_ref=="${userId}"]`])
    .commit();
}

한번에 여러 데이터 변경

transaction을 사용

export async function follow(myId: string, targetId: string) {
  return client
    .transaction() //
    .patch(myId, (user) =>
      user
        .setIfMissing({ following: [] })
        .append('following', [{ _ref: targetId, _type: 'reference' }])
    )
    .patch(targetId, (user) =>
      user
        .setIfMissing({ followers: [] })
        .append('followers', [{ _ref: myId, _type: 'reference' }])
    )
    .commit({ autoGenerateArrayKeys: true });
}

export async function unfollow(myId: string, targetId: string) {
  return client
    .transaction() //
    .patch(myId, (user) => user.unset([`following[_ref=="${targetId}"]`]))
    .patch(targetId, (user) => user.unset([`followers[_ref=="${myId}"]`]))
    .commit({ autoGenerateArrayKeys: true });
}

'React > 라이브러리' 카테고리의 다른 글

리액트에서 CKEditor5 사용  (0) 2023.07.21
리액트에서 네이버 스마트 에디터 구현  (0) 2023.07.20
SWR  (0) 2023.06.20
Mongo DB  (0) 2023.06.15
NextAuth.js  (0) 2023.06.11
Comments