javascriptreactjsnext.jssanitygroq

API Post request to sanity patch query takes upwards of 2 seconds to complete


I'm struggling to understand what could be causing a slow response from the server, upwards of 2 seconds for a simple patch. I've gone ahead and posted an example to help better illustrate the problem. Right now if you swipe right on a card, it will kick off a saveLike and saveVote. Both will fetch data from Card.js about what card you swiped right on and your userID to save to. I'm running next.js with sanity.io, using yarn dev and yarn start respectively. Even insight on how to debug what could be causing a long wait period for a query would be super helpful long term

#context

const handleRightSwipe = async (cardData, votesData) => {

    try {

      await fetch('/api/saveLike', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body:  JSON.stringify({
          likedCards: cardData,
          currentUser: "abc123",
        }),

      })
      // deduct one incrementally 
      let votesAmount = votesData--
      try {
        await fetch('/api/saveVote', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body:  JSON.stringify({
          _id: "abc123",
          votes: votesAmount
        }),
      })

    } catch (error) {
      console.error(error)
    }
      // set vote tally the latest amount
      setVotesData(votesAmount)
      // request vote tally be updated on the client side
      requestVoteAmount(userID)
    } catch (error) {
      console.error(error)
    }
  }

# saveVote

import { client } from '../../lib/sanity'

const saveVote = async (req, res) => {
  try {
    await client
      .patch(req.body._id).set({votes:req.body.votes}).commit()
    res.status(200).send({ message: 'success' })
  } catch (error) {
    res.status(500).send({ message: 'error', data: error.message })
  }
}

export default saveVote

#saveLike

import { client } from '../../lib/sanity'

const saveLike = async (req, res) => {

  try {

    await client
      .patch(req.body.likedCards._id)
      .setIfMissing({'likes': []})
      .insert('after', 'likes[-1]',[
        {
          _ref: req.body.currentUser,
          _type: "reference",
        },
      ])
      .commit({
        autoGenerateArrayKeys: true,
      })

    res.status(200).send({ message: 'success' })
  } catch (error) {
    res.status(500).send({ message: 'error', data: error.message })
  }

}

#Card

import React, { useState, useMemo, useContext, useRef, useEffect } from 'react'
import { Context} from '../context/Context'
import TCard from 'react-tinder-card'

const Card = () => {

  const { cardsData, votesData } = useContext(Context)
  const { handleRightSwipe, handleLeftSwipe, currentAccountAddress } = useContext(Context)
  const [currentIndex, setCurrentIndex] = useState(cardsData.length - 1)
  const currentIndexRef = useRef(currentIndex)
  const childRefs = useMemo(
    () =>
      Array(cardsData.length)
        .fill(0)
        .map((i) => React.createRef()),
    [cardsData.length]
  )

  const updateCurrentIndex = (val) => {
    setCurrentIndex(val)
    currentIndexRef.current = val
  }
const canVote = votesData > 0
const swiped = (direction, card, index) => {
  if (!canVote) return
  if (votesData > 0) {
    if (direction === 'right') {
      const voterAmount = votesData--
      updateCurrentIndex(index - 1)
      handleRightSwipe(card, currentAccountAddress, voterAmount)
    }
    if (direction === 'left') {
      const voterAmount = votesData--
      updateCurrentIndex(index - 1)
      handleLeftSwipe(card, currentAccountAddress, voterAmount)
    }
  }
  else {
  }
}
const outOfFrame = (idx) => {
  currentIndexRef.current >= idx && childRefs[idx].current.restoreCard()
}
  return (
    <div>
      {
        <div>
        {cardsData.map((card, index) => (
          <TCard 
            card={card}
            key={card.name}
            ref={childRefs[index]}
            preventSwipe={['up', 'down']}
            onCardLeftScreen={() => outOfFrame(card.name, index)}
            onSwipe={(dir) => swiped(dir, card, index)}>
              <div
              style={{ backgroundImage: `url('${card.imageUrl}')` 
           >
              </div>
          </TCard> ))}
        </div>
      }
    </div>    
  )
}
export default Card

Solution

  • The mutation API has a visibility parameter that defaults to sync. This means it will wait for the data to be ready to be queried before it returns - which you quite often do not need (I consider "update then refetch" an antipattern).

    To speed up your mutations, use the async visibility. In your code, you can do this by passing visibility: 'async' in your commit() calls:

    await client
      .patch(req.body.likedCards._id)
      .setIfMissing({'likes': []})
      .insert('after', 'likes[-1]', [
        {
          _ref: req.body.currentUser,
          _type: "reference",
        },
      ])
      .commit({
        autoGenerateArrayKeys: true,
        visibility: 'async',
      })