Okay, so now we also know how
to work with our API routes inside of getStaticProps.
We don't send the request there,
we just execute the code directly in getStaticProps
or getServiceAddProps.
Now let's talk about dynamic API routes.
What's that?
Well, let's say you don't just wanna have /api/feedback
which handles post and get requests,
but you also wanna support /api/feedback/some feedback ID
to just fetched a single piece
of data for that specific feedback item,
because maybe you need that somewhere on your page.
For example, on the feedback page, you could say that
for every list item you're rendering here,
you also have like a show details button.
And when that button is clicked,
you wanna show the details for that feedback item.
And hence you want to fetch the data,
the full data for that feedback item.
Now we are
of course actually fetching the full feedback data here.
And we could just use client inside JavaScript
to use that already loaded data for that.
But let's assume that we're not fetching the full data here,
but that instead we are only getting the ID
and the text and not the email address.
And therefore when this button is clicked,
we wanna fetch the full data again,
but not for all feedback items,
but for this single feedback item.
And that's what you could use a dynamic API route for,
because we already know dynamic pages
where you create a page with
that square bracket notation, like this.
This would then allow
for a request sent to /feedback/some-id.
And some-id would be interpreted
as a value for this ID placeholder
and you could then use it inside of that page component
and so on.
That's what we already learned before.
Now that's for regular pages.
We can use a similar feature for API routes,
because it's also not unrealistic
that we wanna send the request to /api/feedback
and then the ID of a specific feedback
to then load the data for that specific feedback.
And for this, we need a new file because here
in feedback.js, we only handle the requests
to /api/feedback/nothing.
Hence in the API folder,
we can add a dynamic API route and we do that
in exactly the same way as we do it for a regular pages.
We use square brackets and then any place holder name
of our choice, like for example id or feedbackId
or whatever you want.
And I'll go with feedbackId.
So now we have a dynamic API route file.
In there, we still define our handler function
and we still export that.
So just as in the other file,
because it works in exactly the same way.
This API route works in exactly the same way,
it's just dynamic.
So for dynamic path segments.
So therefore in here, we might now want to fetch the data
for a specific piece of feedback.
And for that of course,
we need to know which concrete value was encoded
in the URL as a value for this placeholder.
And we can get access
to that again, through this request object
which we should accept together with that response object.
And there, we learned that we have body
for accessing the submitted data,
method for finding out which kind of request it was.
And we also have query for getting access
to query parameters and regular parameters.
So we can get access and get our feedbackId
by accessing req.query.feedbackId,
.feedbackId because I encoded feedbackId
between the square brackets here in my file name.
So that gives us access to the concrete feedbackId
that was part of the URL
when that request hit that handler.
And now we can use that feedbackId
to retrieve a specific feedback item
from the feedback json file.
For this, I still wanna get access to that file.
So I will still import my two functions
from that other file here.
So from the feedback.js file, the buildFeedbackPath
and the extractFeedback functions,
again we could outsource them
in some global helpers file if we wanted to.
And then I'll construct my file path
by calling buildFeedbackPath
and get my feedbackData by calling extractFeedback
and passing file path as an argument.
Now, feedbackData is then an array of all items.
And now here,
I just want to get all the data for one specific item.
So since this is an array,
we can of course just call feedbackData.find
to find one single item
which then executes a function on every item
to find out whether
that is the item we're looking for or not.
And the item we're looking for is the item where feedback.id
is equal to feedbackId.
So that is then the selectedFeedback.
And that's the kind of data we now want
to send back with that for incoming requests.
And for this, we used the response object,
set a status of 200 and set our json response body data
which could carry an items key
which is an object here where I set the feedback key,
lets say, to selectedFeedback.
And now that would return a feedback for a selected ID.
Now, just to make that crystal clear,
your dynamic API routes,
cannot just handle get requests.
Here, I'm not checking the request method at all
which means that for all incoming requests,
I'm just sending back this json data.
But we could all check the request method here
and do something different for post requests
if we needed to.
For example, you could check for delete requests.
And if a delete request is sent for a specific feedback ID,
you could execute some code that deletes
that feedback from our stored feedback items.
It's not a functionality I need here,
but it is something you could also build.
So dynamic routes work for all request methods,
put, post, delete, get and so on
and you can of course differentiate what you do
inside of your handler function, with if checks.
Here, I just wanna return my selected feedback no matter
which method was used though
and therefore that's the code we can use.
Now we added this API route.
Now we can use it in our feedback page.
Here, when this button is clicked,
I wanna send the request to this dynamic API route
to fetch the details for a single feedback.
And for this and the feedback page component,
we can add a function,
loadFeedbackHandler or whatever you wanna call it.
And then in here, send the request.
So now that's connect loadFeedbackHandler to this button
and with onClick and in loadFeedbackHandler,
we now need to know for which id to load the feedback.
So we expect id as a parameter
and to make sure that this id is passed in,
when we bind our loadFeedbackHandler
to the onClick prop, when we pass it into onClick,
I'll call bind on that function,
which is a built in JavaScript method
to pre-configure this function for a future execution.
If it's not clear how bind works,
attached you'll find an additional resource on that,
which clarifies it.
Bind in the end allows us to pre-configure this function.
So it does not execute the function yet,
but it pre-configures it for future execution.
And for example, allows us to pre-configure parameter values
that will be received here.
Now, the first value, the first argument we pass
to bind is a value for the this keyword inside
of this function.
We don't care about that here,
so we can set this to null.
And then the second value we pass to bind,
will be the value for the first argument,
the first parameter received by that function.
And here that should be item.id
so that this button,
when it's clicked or this function execution,
uses the id of the item we're currently rendering.
So that's then the value which we receive here.
And then we can use the fetch function
to again, send the request.
Send the request to /api/
and then the feedback id.
So we add id to that path
or we build that with the template literal notation,
with back ticks and sent this to /api/
and inject id like this.
Either way, this produces a URL like /api/some-feedback-id
and that will then trigger this dynamic route.
Now we're still working with promises here.
So we'll then still add a then block
to get our response eventually and parse that data.
We could also add error handling here,
but I'll not do it here to keep this shorter.
And then we got this data
which we can use in this second, then block.
Now here, we might want to render the details.
So again, we can use useState
for this to update our component
and what's rendered once we got the data.
So from react, I'll import useState here
and then set up some state for this component.
The feedbackData, let's say with the setFeedbackData,
state updating function, where we call useState.
And initially that's undefined.
We have no starting value, but in this then block,
once we have the data fetched from our API,
we can call setFeedbackData to set data.feedback,
like this as our new state.
Now data.feedback, because in this dynamic API route,
I'm setting a feedback property in that response object.
So that is the property holding the selected feedback data.
So that full feedback object fetched
from feedback json.
And therefore it's this property named feedback
which I wanna access here in my front end code
as well as my feedback data.
That is standard object fetched from feedback json,
which I set as my feedback data here.
Now, when that's called, the component will be re-evaluated,
because the state changed.
And we can utilize this
to output the email address for this feedback.
So when that button was clicked,
we now wanna show the email address.
And since I always just have feedback data
for one specific feedback loaded,
the way my component is designed here,
I'll do this above the unordered list.
Use fragment, import it from react,
because adjacent JSX code isn't allowed,
otherwise move that in here.
And then here, render something conditionally.
If feedbackData is set,
then I wanna output, let's say a paragraph
where I just output feedbackData.email.
The .email because feedbackData will be a single piece
of data from feedback json, so such an object.
And in those objects, we do have an email property.
So we can access that here.
And then we'll show up the data for the loaded feedback
for a single piece of feedback above the list of feedbacks.
Now that is of course,
all just some very basic unstyled dummy code
to show you how you can interact with those API routes.
Hence if you now save everything and reload /feedback,
we do have to show details button.
And if we click it, we see eventually the email address
of that feedback shows up at the top.
Now, as I mentioned before,
this is kind of redundant, because with getStaticProps,
we already fetched the full feedback data.
So we have all that data exposed through props
in that component already.
So sending another request for a single piece
of data here is redundant, but of course it's not redundant
for you to know about this dynamic API route feature
which is why I used this example for showing this to you.
Because this is how you can send requests
to dynamic API routes
and how you can set up dynamic API routes
to execute service side code
for dynamic pieces of data encoded in the path.