Amplify-js: How to subscribe Create and Delete with <Connect />

Created on 14 Feb 2019  路  15Comments  路  Source: aws-amplify/amplify-js

* Which Category is your question related to? *
API / GraphQL

* What AWS Services are you utilizing? *
AWS AppSync

* Provide additional details e.g. code snippets *
Hello all,

I'm trying to subscribe any updates including create, delete and update in my GraphQL backend using <Connect />, but all I could find from Amplify API doc was just an example which is subscribing Create events only like following.

<Connect
    query={graphqlOperation(queries.listTodos)}
    subscription={graphqlOperation(subscriptions.onCreateTodo)}
    onSubscriptionMsg={(prev, { onCreateTodo }) => {
        console.log ( onCreateTodo );
        return prev; 
    }}
>

Anyone know how to subscribe create and delete at the same time with <Connect />?

investigating pending-close-response-required question

Most helpful comment

I just realized I misread your post (sorry, busy day).
So my other post may not answer your question, but maybe this will:
you'll have to use a custom subscription. For example, amplify probably creates something like this in a subscriptions.js file:

export const onCreatePost = `subscription OnCreatePost {
  onCreatePost {
    id
    field1
    field2
  }
}
`;
export const onDeletePost = `subscription OnDeletePost {
  onDeletePost {
    id
    field1
    field2
  }
}
`;

And then you can only select onCreatePost OR onDeletePost

But you could create a new subscription in a custom file:

export const onCreateOrDeletePost = `subscription onCreateOrDeletePost {
  onCreatePost {
    id
    field1
    field2
  },
  onDeletePost {
    id
    field1
    field2
  }
}
`;

I think that'll work, worth a quick try at least.

There may be a more elegant way of doing this without doing a custom subscription.js file, but I don't know it.

All 15 comments

Hey I'm also struck by this question, this would be a fantastic feature to have on <Connect/>.
The only way I could subscribe to multiple event sources was to modify the connect component. Please excuse any hackiness in the PR I'm still getting familiar with the amplify code base.
Thanks!

You can also extend the connect component, which is what I did. See here: #2527

wizawuza, could you give an example of how that would look?
In the source it looks like <Connect /> can only be bound to one subscription at a time.

this.subSubscription = observable.subscribe(...)

How can you extend the component to listen for multiple events (create,update,delete) if only one subscription can be bound to <Connect/> internally?

I just realized I misread your post (sorry, busy day).
So my other post may not answer your question, but maybe this will:
you'll have to use a custom subscription. For example, amplify probably creates something like this in a subscriptions.js file:

export const onCreatePost = `subscription OnCreatePost {
  onCreatePost {
    id
    field1
    field2
  }
}
`;
export const onDeletePost = `subscription OnDeletePost {
  onDeletePost {
    id
    field1
    field2
  }
}
`;

And then you can only select onCreatePost OR onDeletePost

But you could create a new subscription in a custom file:

export const onCreateOrDeletePost = `subscription onCreateOrDeletePost {
  onCreatePost {
    id
    field1
    field2
  },
  onDeletePost {
    id
    field1
    field2
  }
}
`;

I think that'll work, worth a quick try at least.

There may be a more elegant way of doing this without doing a custom subscription.js file, but I don't know it.

wizawuza that worked!
I'm still new to GraphQL but your solution is making me see the light!

Also this solution is way cleaner then dealing with an array of subscriptions like in my PR. I'll take the trade off of having to manage a separate subscription file.

You can create Listeners on componentDidMount! I am creating this code later this arvo and will post ASAP.

Please create a question on stackoverflow too and post the link here. That may help ppl in the future too!!

Talk to you soon!

Thanks for posting @wizawuza . I am able to subscribe to a create, update, and delete successfully by batching the subscriptions. My question is how can I know which mutation ran? I am trying to update a table and would need to either update, add, or remove entries based on what happens. I would also like to leverage the connect component.

I could also try and refetch the connect query, but am not sure how to do this.

Any thoughts?

Thanks!

@sadnub that one's easy thankfully.
In your subscription function:

onSubscriptionMsg={(prev, updatedQuery) => {
        console.log (updatedQuery);
        return prev; 
    }}

You'll notice from the console.log, it'll output something like:
updatedQuery.onCreatePost

OR

updatedQuery.onDeletePost

So, what you would do is either use an if/then/else if block or switch/case:

if(updatedQuery.onCreatePost) {
  // do something for a newly created post
}
else if(updatedQuery.onDeletePost) {
  // do something for a deleted post
}

Thank you that worked great! Here is my final product to help anyone else.

I am saving the table item in operationIndex so I can modify the internal connect list.

      updateCustomerTable (prevData, newData) {

        let index
        if (this.operationIndex){
          index = prevData.data.listCustomers.items.indexOf(this.operationIndex)
          this.operationIndex = null
        }

        if (newData.onCreateCustomer) {
          prevData.data.listCustomers.items.push(newData.onCreateCustomer);

        } else if (newData.onDeleteCustomer) {
          prevData.data.listCustomers.items.splice(index, 1)

        } else if (newData.onUpdateCustomer) {
          Object.assign(prevData.data.listCustomers.items[index], newData.onUpdateCustomer)
        }

        return prevData.data

      }

@wizawuza is this way work with mutations? and how to marge two mutations?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been automatically closed because of inactivity. Please open a new issue if are still encountering problems.

In the graphql subscriptions file I see the following the top
/* eslint-disable */
// this is an auto generated file. This will be overwritten

That is a bit of a concern no?

This solution doesn't work for me.
It throws the error Connection failed: {"errors":[{"errorType":"DuplicatedOperationError","message":"Duplicated operation with id af9796e9-e246-441a-28ab-416256b72067"}]}

Looks like an update to AppSync disabled this ability as descibed in more detail on this issue: https://github.com/aws-amplify/amplify-js/issues/4813

@wizawuza solution did not work for me, doesn't even console something

Subscription

export const onCreateOrDeleteTodo = /* GraphQL */ `
  subscription onCreateOrDeleteTodo {
    onCreateTodo {
      id
      name
      description
    }
    onDeleteTodo {
      id
      name
      description
    }
  }
`;

My Connect

 <Connect 
        query={graphqlOperation(listTodos)}
         subscription={graphqlOperation(subscriptions.onCreateOrDeleteTodo)}
         onSubscriptionMsg={(prev, { onCreateTodo, onDeleteTodo }) => {
            console.log(onCreateTodo)
            return prev; 
          }}
   >
Was this page helpful?
0 / 5 - 0 ratings