
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Complete source code for this lesson is available at
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 To know whether the user has saved or not saved the question before, we can create another server action within collection.action.ts file.
00:00:11 I'll go ahead and copy this one because all server actions follow a similar structure and I'll paste it below, but I'll rename it to has saved question.
00:00:22 It'll take in the same collection base programs, the response and everything.
00:00:26 Same thing for the error, same thing for the question ID and the user ID, but now the output will be just a tiny bit simpler.
00:00:33 In the try block, we don't need to fetch the question.
00:00:36 What we need is only to fetch the collection.
00:00:39 Once we do that, we can immediately just return the state of that collection.
00:00:44 That'll look something like this.
00:00:47 Collection is a weight collection find one where this user liked this question and then return success to true and the data of saved can be set to exclamation mark,
00:00:59 exclamation mark.
00:01:00 So this is a double knot collection.
00:01:04 Now, what does this mean?
00:01:06 Why am I using a double exclamation mark right here?
00:01:09 This is a notation used to transform something into a Boolean variable.
00:01:13 Why?
00:01:14 If a collection doesn't yet exist, it'll be a falsi value.
00:01:18 And when you apply not to a falsi value, it gets converted to true.
00:01:22 And then when you apply another not to that true, you get false, which means that a collection doesn't exist.
00:01:29 False.
00:01:30 Or, in this case, the question has been saved to a collection.
00:01:34 Or, in a similar way, if you say double-node to truthy value, then of course, first-node will convert it into false, and then the second one will convert
00:01:45 that false into true.
00:01:48 So this is a nice way to just get access to a simple boolean value of whether it has been saved or not.
00:01:55 Now, if we head over to the question ID, so that's going to be question ID page, question details, right below where we see has voted promise,
00:02:05 we can say cons has saved question.
00:02:09 promise and make it equal to hasSavedQuestion to which we need to pass a question ID of a question.underscoreID.
00:02:19 And now we can pass this hasSavedQuestion promise into the saveQuestion component just like so.
00:02:28 We can then accept it within the saveQuestion I'll add a has saved question promise, and I'll say that it is of a type promise that gets resolved into
00:02:40 a Boolean.
00:02:41 After that, we can use the use hook as you learned before, const, destructure the data, and make it equal to the call of the React's use hook to which
00:02:51 we have to pass that hasSaved question promise.
00:02:55 Then from the data, we can just destructure the hasSaved variable const saved, which we can rename to hasSaved, is equal to data or just an empty object
00:03:08 if data doesn't exist.
00:03:09 Now we need to remove this hasSaved that is static because we have the dynamic one and it looks like data is complaining a bit saying that property data
00:03:19 does not exist on a type boolean.
00:03:21 So yeah, this is my mistake right here.
00:03:24 The hasSaved question actually gets resolved in a promise of a type action response that contains a value of saved, which then is a boolean.
00:03:38 So now it doesn't complain, we have access to the hash saved, and you can see that the star is turned on, but if I click it again,
00:03:46 question unsaved successfully, it looks good.
00:03:49 So if I reload, it is unsaved.
00:03:51 To make sure that the value changes immediately, we can head back over into Collection Actions.
00:03:57 And here, we can scroll up to where we are trying to delete the question.
00:04:02 Because if you think about it, the issue is not when you're trying to save the question.
00:04:06 That one works.
00:04:07 See?
00:04:08 I save it and it changes.
00:04:09 But then when I try to unsave it, well, then it's stuck.
00:04:13 So that made me think that the issue must be right here where we're deleting the save from a collection.
00:04:19 And check this out, find by ID and delete collection right here should have underscore ID.
00:04:27 That was the issue, which is going to then send success to true and the modified data of saved false.
00:04:34 So now that I have added the underscore ID right here, if I try to save it, it saves.
00:04:39 If I unsave it.
00:04:42 Oh, it didn't do anything.
00:04:45 Let me reload.
00:04:48 And now it removed it.
00:04:49 Let's try it one again.
00:04:50 I click it, saved.
00:04:52 I unclick it.
00:04:54 Nope, still doesn't do anything.
00:04:56 Oh, and I'm actually super glad this happened.
00:04:58 The reason why it is not being, well, let me use the word revalidated, that's a hint for you.
00:05:04 Well, that's because we are returning right here, so it doesn't get a chance to revalidate.
00:05:09 So we also have to put a revalidate here before we delete that save functionality in the same way that we revalidate before we save the question.
00:05:20 So if I add it, now it's unsaved, I click it, gets saved, I unclick it, gets unsaved.
00:05:27 Beautiful.
00:05:28 And let's also quickly head over into where we used this save question.
00:05:33 And let's just wrap it into a proper div so it shows a bit more nicely next to the votes.
00:05:38 Next to justify end, I'll also add items-center as well as a gap of four in between the elements.
00:05:45 And that'll give it some breathing room.
00:05:47 So now we can properly save and unsave questions.
00:05:51 In this lesson, we accomplish the functionality of finding out the current status of whether the question has been saved or unsaved.
00:06:01 So let's head over into our source control and let's say show user has voted question.
00:06:09 Commit it and sync it.
00:06:11 And then in the next lesson, we can focus on actually putting to use this entire saving functionality.
00:06:18 I mean, what does it mean to just save a question?
00:06:21 We actually have to show all of our saved questions somewhere.
00:06:25 We'll do that on the collections page.