Archived student lesson
Add LikeBundle and LikeFeed Mutations
Part of End to End React with Prisma 2
Objective: Create mutations to allow us to like bundles and feeds.
Now that we have a way to create feeds and bundles, let’s figure out how we can like them. This will show up on the UI as a heart button that when we click it, it will turn red and the like count will increment by one. Similarly, clicking it again will unlike the item and decrease the like count by one. We’ll represent this by adding a new field called likes on our feed and bundle objects. Liking something will call the prisma connect function to connect the user’s object to that feed or bundle. Unliking something will call the prisma disconnect function.
Let’s start by adding the typeDefs. Modify the typeDefs to add likeBundle and likeFeed to the mutations section.
utils/api/typeDefs.ts
type Feed {
id: String
name: String
url: String
author: User
tags: [FeedTag]
bundles: [Bundle]
likes: [User]
}
type Bundle {
id: String
name: String
description: String
author: User
tags: [BundleTag]
feeds: [Feed]
likes: [User]
}
type User {
id: String
auth0: String
nickname: String
picture: String
bundles: [Bundle]
feeds: [Feed]
feedLikes: [Feed]
bundleLikes: [Bundle]
}
# more defs below...
input LikeBundleInput {
bundleId: String
likeState: Boolean
}
input LikeFeedInput {
feedId: String
likeState: Boolean
}
# more definitions below
type Mutation {
clearAll: String
createFeed(data: FeedCreateInput): Feed
createBundle(data: BundleCreateInput): Bundle
likeBundle(data: LikeBundleInput): Bundle
likeFeed(data: LikeFeedInput): Feed
}
The two mutations will take the id of the bundle or feed that we want to like and a likeState boolean which is the desired state that it should be- that is if we want to like an item, we pass a likeState: true and if we want to unlike something we pass a likeState: false. Having this flexibility to both like and unlike something with the same mutation allows us to make the most out of our mutations.
Turning to our resolvers, we first call createFieldResolver for the two new likes fields that we added to the Feed and Bundle models. Then, we can create our two likeBundle and likeFeed resolvers. These will specify a connect state which allows us to either connect or disconnect the current user to the bundle or feed specified with either feedId or bundleId. Since the item already exists, we will be calling update rather than create or findOne/findMany that we’ve used before. The update function still takes the data block that we’ve used in the create but it also has a new where block that allows us to specify the id of the item that we are trying to update.
utils/api/resolvers.ts
const resolvers = {
Feed: {
...createFieldResolver('feed', 'author'),
...createFieldResolver('feed', 'bundles'),
...createFieldResolver('feed', 'likes'),
...createFieldResolver('feed', 'tags'),
},
Bundle: {
...createFieldResolver('bundle', 'author'),
...createFieldResolver('bundle', 'feeds'),
...createFieldResolver('bundle', 'likes'),
...createFieldResolver('bundle', 'tags'),
},
// more resolvers above
likeBundle: (parent, { data }, { prisma, user }) => {
const { bundleId, likeState } = data
const connectState = likeState ? 'connect' : 'disconnect'
return prisma.bundle.update({
where: { id: bundleId },
data: { likes: { [connectState]: { id: user.id } } },
})
},
likeFeed: (parent, { data }, { prisma, user }) => {
const { feedId, likeState } = data
const connectState = likeState ? 'connect' : 'disconnect'
return prisma.feed.update({
where: { id: feedId },
data: { likes: { [connectState]: { id: user.id } } },
})
},
// more resolvers below
}
Let’s now make sure the mutations work. Let’s first try liking the bundle that we created:
mutation likeBundleMutation($data: LikeBundleInput) {
likeBundle(data: $data) {
...BundleFragment
feeds {
...FeedFragment
}
}
}
fragment FeedFragment on Feed {
id
name
url
likes {
...AuthorFragment
}
tags {
...FeedTagFragment
}
author {
...AuthorFragment
}
}
fragment BundleFragment on Bundle {
id
name
description
tags {
...BundleTagFragment
}
author {
...AuthorFragment
}
likes {
...AuthorFragment
}
}
fragment AuthorFragment on User {
id
auth0
picture
nickname
}
fragment BundleTagFragment on BundleTag {
id
name
}
fragment FeedTagFragment on FeedTag {
id
name
}
{
"data": {
"bundleId": "10",
"likeState": true
}
}
Make sure that the bundleId equals the id that you used when you created your bundle. If you forget, you can always run a bundles query and see what Ids come back and then like one of those. What you should see in the return is a field called likes that has an array with a single user which is the one that we are hard-coding.
From the mutation we just sent above, leave the fragments but swap likeBundleMutation for this likeFeedMutation:
mutation likeFeedMutation($data: LikeFeedInput) {
likeFeed(data: $data) {
...FeedFragment
bundles {
...BundleFragment
}
}
}
then, issue the following variables along with the request:
{
"data": {
"feedId": "1",
"likeState": true
}
}
We should also see that this request comes back successfully and that this feed now has 1 like on it.