End to End React with Prisma 2
Start at the beginning and work your way through this project. The code for each step as well as the finished project can be found in the Github repository.
10. Add LikeBundle and LikeFeed Mutations
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
ts
type Feed {id: Stringname: Stringurl: Stringauthor: Usertags: [FeedTag]bundles: [Bundle]likes: [User]}type Bundle {id: Stringname: Stringdescription: Stringauthor: Usertags: [BundleTag]feeds: [Feed]likes: [User]}type User {id: Stringauth0: Stringnickname: Stringpicture: Stringbundles: [Bundle]feeds: [Feed]feedLikes: [Feed]bundleLikes: [Bundle]}# more defs below...input LikeBundleInput {bundleId: StringlikeState: Boolean}input LikeFeedInput {feedId: StringlikeState: Boolean}# more definitions belowtype Mutation {clearAll: StringcreateFeed(data: FeedCreateInput): FeedcreateBundle(data: BundleCreateInput): BundlelikeBundle(data: LikeBundleInput): BundlelikeFeed(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
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 abovelikeBundle: (parent, { data }, { prisma, user }) => {const { bundleId, likeState } = dataconst 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 } = dataconst 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:
graphql
mutation likeBundleMutation($data: LikeBundleInput) {likeBundle(data: $data) {...BundleFragmentfeeds {...FeedFragment}}}fragment FeedFragment on Feed {idnameurllikes {...AuthorFragment}tags {...FeedTagFragment}author {...AuthorFragment}}fragment BundleFragment on Bundle {idnamedescriptiontags {...BundleTagFragment}author {...AuthorFragment}likes {...AuthorFragment}}fragment AuthorFragment on User {idauth0picturenickname}fragment BundleTagFragment on BundleTag {idname}fragment FeedTagFragment on FeedTag {idname}
json
{"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
:
graphql
mutation likeFeedMutation($data: LikeFeedInput) {likeFeed(data: $data) {...FeedFragmentbundles {...BundleFragment}}}
then, issue the following variables along with the request:
json
{"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.