Module 6 Summary
This lesson is a summary of the work we've done in Module 6.0.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
[00:00 - 00:23] In this module, we spent our efforts in attempting to have the client be able to query information for a certain user when they visited the relevant user page. On the server side, we've created a single query root level user field that attempts to find a user document from our user's collection based on the ID and put argument provided.
[00:24 - 00:50] And the user document to be returned, or the user object to be returned to the client is to have certain fields that we want the client to access, such as the name of the user, the avatar, contact, whether the user has wallet information, income, as well as two paginated fields we've created as well, called bookings and listings. Bookings refer to the bookings that the user has made, while listings refer to the listings that the user has created.
[00:51 - 01:00] We've created a few new resolver maps. The user resolver map is responsible in having the resolver functions that per tain to the user.
[01:01 - 01:18] The root level user query resolver function is fairly straightforward, and we simply try to find a user document in the user's collection where the underscore ID field is equal to that of the ID argument passed in. We do do another check, however, and we do specify to say that the person making the request is the actual viewer.
[01:19 - 01:34] In that context, we can add the authorized field to this user object that this user resolver is going to return. The reason being is that the other fields within the user object, such as perhaps the income or the bookings, is we consider sensitive information.
[01:35 - 01:45] So in this context, we check to say that is this user authorized to see this information? If so, we simply provide the income and the bookings information.
[01:46 - 02:08] We specify that the income of the user as well as the bookings that the user has made is sensitive information that should only be shown to the person making the request if they are the user that they're looking at. So this is why in our roots level user query function, we check that does the viewer exist and we determine this viewer object exists from an authorized function.
[02:09 - 02:22] And if it does, we also want to make sure that the idea of this viewer is the idea of the user being queried for. And if so, this user is authorized and as a result, we're able to get the income as well as the bookings information.
[02:23 - 02:36] Now the bookings and listings fields are paginated fields. We've quickly mentioned how within pagination, oftentimes there's two levels of pagination, such as offset based pagination and cursor based pagination.
[02:37 - 03:04] And though we use the context of a Mongo cursor here, the pagination that we're conducting is often recognized as offset based pagination, which is pagination where we return a certain number of elements based on base, the limits, which is basically the quantity we want returned, as well as the page or results of value you want to see. So if in this context, if the bookings field here receives page one and a limit of 10, we essentially return the first 10 items within the first page.
[03:05 - 03:10] The page was two and the limit was 10. We return the 10 items in the second page and so on.
[03:11 - 03:36] And we do this with the cursor capability from Mongo, where we're able to essentially skip elements in the cursor based on the page arguments provided and we're able to use a limit function within this cursor to limit the results that we actually want to retrieve. And we simply return that data, which consists of the total amount of this cursor, which is essentially all the results we can find, as well as information of the actual results, which is the paginated list of bookings.
[03:37 - 03:54] And this is very similar to the listings field we have as well. We apply a limit in a page and in our actual paginated resolver function, we return both the total amount of listings that exist, period, as well as the result, which is the paginated list that we get for a certain limit and a certain page.
[03:55 - 04:18] And since we're resolving this listings and bookings fields within the user object to bookings and listings, we've created their types, which represent what a listing object is to consist of, as well as the type of what a booking object is to consist of . And because of this, we've also needed to create resolver functions for these domains, at least for the functions that we need resolved.
[04:19 - 04:36] So for the listing resolver or the listing object, we needed to resolve an ID field, which is the underscore ID field from the listing document converted to its string representation. And for the booking, we had to do something similar and it essentially resolved an ID field from the underscore ID filled within the document.
[04:37 - 05:06] And for the listing field within a booking object, we had to do something similar, but slightly different because the listing field within a booking document is an ID . However, for our GraphQL API, we actually want to return a listing object, not just the ID, which is why in our resolver function, we have to resolve the fact that we need to find a listing in the listings document where the idea of this listing is the listing field within the booking resolver object passed in here.
[05:07 - 05:29] Let's head over to the client to now see the work we've done in our React application. We've created the user GraphQL query document and in our query document, we essentially specified that we want to query for practically all the fields available, such as the ID, name, avatar, etc., as well as all the bookings, information for this particular user , and all the listings information for this certain user.
[05:30 - 05:47] And then in our sections, user component is where we construct the UI for this user page. And this particular component is shown in the slash user route, which is a dynamic route that is to have the ID of the user as a dynamic URL parameter.
[05:48 - 06:04] And it's with this dynamic URL parameter, we provide as the value for the ID variable for when we actually conduct the user query. We specified a limit of four, and this limit is shared for both the paginated bookings and listings field.
[06:05 - 06:16] Well, look at the user GraphQL document. We see that it retrieves a particular limit, and this limit, it tells us which number of elements is going to be returned for both the bookings and listings field.
[06:17 - 06:30] If we wanted to, we could have two arguments here to conduct which one can be different for each other. In this case, we specified it on our clients, we expect that at most only four bookings and listings will be shown at a time.
[06:31 - 06:39] And we initialize their page values as one at the very beginning. When this user query is ever loading, we just show a page skeleton.
[06:40 - 07:10] When this user query ever errors, we continue to show the page skeleton, but now place an error banner up top that tells the user something might have went wrong. Once data is available, we simply retrieve the user object, and from the user object, we get the listings and bookings fields within this user object, and we then construct the three different child components we expect to show, which is essentially the user profile information which contains information about the user's image, email, and later on will be the area where the user will be able to connect the stripe.
[07:11 - 07:17] And then we conduct the two different paginated lists, which are the listings of the user, as well as the bookings of the user as well.