What is the correct way to delete a post within a graphql subscription?

What is the correct way to delete a post within a graphql subscription?


1

I’m working on a project where I have posts that are created and shown on a screen. I’ve done this using graphql subscriptions for real time updating of posts, but I need the user to also be able to delete their own posts and for that update to be shown in real time. The examples that I’ve found which are some what similar are old and use a different syntax, so I able to apply them to my project. Currently, I have:

import User from '../../models/User.js';
import Posts from '../../models/Posts.js';
import { requireAuth } from '../../services/auth.js';
import { PubSub } from 'graphql-subscriptions';
import { ObjectId } from "mongodb";
// need to change for product PubSub is not advised for production!!!

const pubsub = new PubSub();
const NEW_MESSAGE_EVENT = 'newMessage';

export default {
  getPost: async (_, { offset, limit, topic },{user}) => {
  try {
    const post = await Posts
    .find({"post.topic":topic})
    .skip(offset)
    .sort({"post.dateSent": -1 })
    .limit(Math.min(limit, 100))   
    return post
      } catch (error) {
        throw error;
      }
    },

    createPost: async (_, { input }) => {
      try {
        const post = new Posts(input);
        await post.save();
        pubsub.publish('NEW_POST_EVENT', { newPost: post });
        return post;
      } catch (error) {
        throw error;
    }
  },

  newPost: {
    subscribe: () => pubsub.asyncIterator(['NEW_MESSAGE_EVENT'])
 },

};
  

in my backend and:

...
export const GET_POST = gql`
  query ($offset: Int!, $topic: String) {
    getMessage(offset: $offset, limit: 20, topic: $topic) {
     _id
     sender {
       senderId
     }
      post {
        text
        topic
        dateSent
      }
    }
  }
`;

export const CREATE_POST_MUTATION = gql`
  mutation createPost($input: PostInput!) {
    createPost(input: $input) {
        post {
          text
          dateSent
        }
      }
  }
`;

export const POST_SUBSCRIPTION = gql`
subscription {
  _id
  newPost {
    sender {
      senderId
    }
     post {
       text
        topic
       dateSent
     }
   } 
  }
`;
export default function PostScreen() {

const [createPost,{ data: createPostDate, error:createPostError}] = useMutation(CREATE_POST_MUTATION)
  async function createPostHandler (item: any) {
    createPost({
    variables: { 
    input: { 
       ...
   }, 
  }})
  }
const {data, loading, error, subscribeToMore, fetchMore: fetchMorePosts} = useQuery(GET_POST,  {fetchPolicy: 'cache-and-network', variables: { offset: 0, topic: ''}})
  useEffect(() => {
  subscribeToMore({
     document: POST_SUBSCRIPTION,
      updateQuery: (prev, { subscriptionData }) => {
         if (!subscriptionData) {
            return prev;
          }
          const newPost = subscriptionData.data.newPost;
          return {
            getPost:[newPost, ...prev.getPost]
          };
        },
        onError: err => console.error(err)
      });
}, []);

const fetchMoreAndUpdateCache = useMemo(() => {
  return async (offset: number) => {
    await fetchMorePosts({
      variables: { offset },
      updateQuery: (prev, { fetchMoreResult }) => {
        if (!fetchMoreResult) {
          return prev;
        }
        
        const moreItems = fetchMoreResult.getPost;
        if(moreItems.length < 1) {
          setStopFetchMore(true);
        }

        return {
          getPost: [...prev.getPost, ...moreItems]
        };
      }
    });
  };
}, []);

const fetchMore = useCallback(() => {
  if(!data || loading || isStopFetchMore) {
    return;
  }

  const offset = data.getPost.length;
  if (offset >= 20) {
    fetchMoreAndUpdateCache(offset);
  }
}, [isStopFetchMore, loading, data]);

return (
...
)
}

in my frontend. I’ve thought of two ways of being able to delete and having it update with the subscription, but I’m not sure if either is the correct or most efficient way. The first way would be changing newPost to updatePost and have have something like:


deletePosts: async (_, { id}) => {
  try {
    console.log('id', ids)
    const deletePost = await Posts.findOneAndDelete({_id:id}});
    pubsub.publish('UPDATE_POST_EVENT', { updatePost: deletePost });
    return deletePost;
  } catch (error) {
    throw error;
}
},

in the backend and try to check for changes in useEffect(() => {subscribeToMore({ document: POST_SUBSCRIPTION,... in the frontend , where maybe I would have to filter out deletePost from the getPost query. The second way I thought this might be possible would be by having a whole separate subscription event: deletePost: { subscribe: () => pubsub.asyncIterator(['DELETE_POST_EVENT'])},, but I’m not 100% sure on how I would use that to update the data in the frontend. I would really appreciate any help or advice on how to do this. Thank you!


Load 5 more related questions


Show fewer related questions

0



Leave a Reply

Your email address will not be published. Required fields are marked *