Let's make some dynamic params with remix.
So I talked about Twitter as an example.
Twitter actually has two dynamic params.
For us, we just have the one.
And so the first thing that we're gonna do is create this file,
app/routes/posts/$slug.
That dollar sign indicates to Remix that we want this to be a parameter.
And so it will match anything that comes after post,
and call whatever that next segment is, slug, in our code.
So let's go to app/routes/posts.
And we'll create a new file called $slug.tsx.
And in this, we're going to have a Remix component, and
I've got a handy little snippet for that.
This is gonna be our PostRoute.
And then we're going to just borrow some of this JSX for what this is gonna return.
And then we need to make a loader that uses the slug param to
find the blog post by its slug.
And we're gonna create a new function in the post server file to do that.
So let's go do that here really quick.
Here we'll export a function called getPost, it takes a slug.
We'll set that to, well, I'll just set it to a string.
And then return prisma.post.findUnique,
where the slug is equal to the one that we've been given.
So now we have a way to get a post by its slug.
And in this case,
we want to select everything because we're going to be displaying the post including
the title markdown, and potentially the created at, and updated at, as well.
So in this case, we don't need to have a select clause or anything like that.
So then in here, we're gonna make a Remix loader.
I've got a handy little snippet to import all the stuff that we need for that.
And we're going to get our post from await getPost.
And the post accepts the slug, so we need to get the slug from somewhere.
So this is the dynamic route params part.
We are going to get a params option in the arguments of our loader.
And params has a slug on it because the name of our file.
So if we name this postId, then this would be postId.
Whatever the name of your file is, that's the convention.
So we'll say slug, because I want it to be slug.
Okay, great, so now we have our post.
We'll just stick that in here as part of the JSON data that we send back.
Turns out we don't need the request, so I'll delete that.
And now our data has our post.
So I'll just say data.post.title.
Now we've got TypeScript complaining about a few things.
But let's just leave it here for now,
just to make sure that everything is working as expected, okay?
So if I go to my first post, ta-da, there we are.
And then, A Mixtape I Made Just For You, and that is working, so we are.
And actually, we can take a look at the network request too,
to make sure that the loader is sending back the data we expect.
Which it is.
Just in review, we created a getPost function to get a post by its slug,
and then a simple remix route that has a loader and
a component for using that loader's data.
Yes, Mark?
>> How do you prevent prop drilling in a larger app?
Can you use, useLoaderData in a child component, or
do you have to pass data from route component down?
>> Yeah, great question.
So yes, so for everybody, terms and all that.
So we've got our Title component that's gonna be in
charge of rendering out the title for our post, right?
So a couple of options here, we can either accept the title and
just render that title out.
That is one option.
And in that case, you would technically be prop drilling to make that work, right?
Or you can, as the question asker asked,
you can actually use useLoaderData directly in this component.
And that totally works.
So wherever the component appears in the route hierarchy,
it will just find the closest parent route and get the data for that one.
So yes, you can avoid it that way.
In practice, interestingly, I don't find myself making
very many subcomponents that care about the route data.
You will obviously, or I shouldn't say obviously.
But it is very common practice to make reusable components like a component
library and things.
And those things really never care about where the data is coming from, right?
They always accept props.
So yeah, you'll absolutely be passing props.
But for the specific routes that you're talking about,
especially since they're nested, they typically don't get very large.
And so I don't find myself even making multiple components.
And when I do, it's only two or three additional components for a given route.
And that is just part of the magic of nested routing, yeah.
>> What if you have nested dynamic segments and
need to access the loader data from the parent dynamic segment?
>> Yeah, that's a great question.
So if we're building Twitter, and
then we're gonna have username, and
then we'll have the status, and then tweetId, right?
So that's the structure that you would have.
And then you've got params here.
You'll have a params.username and a params.tweetId.
I should also mention that params is accessible even from the root component.
So you don't have to be in a nested component to know what the params are.
Even the root component can know what those are.
I should say, I actually don't know whether that's the case for the loaders.
I would have to play around with that.
But most of the time, I can't think of a use case off the top of my head where
the loader would need to know what the subparams are.
But in the component, for sure, you have this useParams hook that
gives you access to the params wherever they are in the application.