reactjsnext.jsswr

How to mutate specific object in an array using SWR


I have the following array

[
{
"idChatPublic": 17,
"idChatRoom": 2,
"idSender": "6c25110d-4256-42e1-8205-b75ece274487",
"username": "Hudson Thadeu Teixeira",
"message": "hello",
"avatar": null,
"createdAt": "12:43",
"chatLike": []
},
{
"idChatPublic": 33,
"idChatRoom": 2,
"idSender": "6c25110d-4256-42e1-8205-b75ece274487",
"username": "Hudson Thadeu Teixeira",
"message": "jam",
"avatar": null,
"createdAt": "13:07",
"chatLike": [
  {
    "idChatLike": 1,
    "idChatPublic": 33,
    "idUser": "",
    "createdAt": "2022-02-14T08:59:34.000Z"
  }
 ]
}
]

How can mutate an specific object of this array and add an object to the "chatLike" array using SWR?

I have the following function:

async function sendLike() {
const newLike = {
  idUser: myUser.userId,
}

mutate(
  async (data) => {
    console.log(data[messageIndex]) // This log returns specific object in the array

    // Handle mutation

  },
  false
)
socket.emit('send_like', newLike)
}

Please guys I've been trying this for a while would be great If someone gives me a hand :D


Solution

  • Note: As of v2.1.0, SWR now supports subscribing to real-time data sources via the useSWRSubscription hook


    Old answer:

    You're using SWR with a websocket, which is an anti-pattern. SWR is meant for managing data that's fetched via REST or GraphQL requests, and it can be configured to refetch data on a regular interval. It's not a real time connection. Websocket on the other hand is real time. Consider if SWR is really best for your project - you probably don't need it.

    Anyway, I also noticed some issues with how your mutate() is written so here's some feedback.

    function sendLike() {
      const newLike = {
        idUser: myUser.userId,
      }
    
      // send request to update the source
      // this is usually an REST request such as 'POST, UPDATE' etc
      socket.emit('send_like', newLike)
    
      // mutate local data
      mutate(
        '/api/chat', // ID must match ID used in the useSWR hook,
        data => data.map(chat => chat.idChatPublic === idChat : {
          ...chat,
          chatLike: [
            ...chat.chatLike
            newLike
          ]
        } : chat),
        false
      );
    }