In the post Data Loader in React Router we saw how to use loader function to fetch data for route component. In this post we'll see how to use data loader with dynamic routes in React.
Data Loading React Router Example
In this example we'll use a loader function to fetch data from API. For API call https://jsonplaceholder.typicode.com/posts resource is used which is a free fake API. In the example Bootstrap 5 is used for styling.
Route Configuration
src\components\routes\Route.js
import { createBrowserRouter } from "react-router"; import Home from "./home"; import NavigationNavLink from "./NavigationNavLink"; import ErrorPage from "./ErrorPage"; import PostList, {loader as PostLoader} from "./PostList"; import PostDetails, {loader as PostDetailsLoader} from "./PostDetails"; import PostLayout from "./PostLayout"; export const route = createBrowserRouter([ {path: "/", element: <NavigationNavLink />, errorElement: <ErrorPage />, children: [ {index: true, element: <Home /> }, {path: "post", element: <PostLayout />, children:[ {index: true, element: <PostList />, loader: PostLoader, hydrateFallbackElement: <h2>Loading...</h2>}, {path: ":postId", element: <PostDetails />, loader: PostDetailsLoader, hydrateFallbackElement: <h2>Loading...</h2>}, ] }, ] }, ])
As you can see there is a Navigation Menu component that is mapped to root route. Nested routes of root route are Home and PostLayout.
PostLayout again has nested routes for PostList to show all the posts and another as a dynamic route for showing details of a particular post by adding postId as path parameter to the URL.
Add this route configuration to RouteProvider.
<RouterProvider router={route}></RouterProvider>
Components used
Navigation Menu, Home and ErrorPage components remain as shown in this post- Data Loader in React Router.
src\components\routes\PostLayout.js
import { Outlet } from "react-router"; const PostLayout = () => { return( <div className="mx-2"> <Outlet /> </div> ) } export default PostLayout;
There is just a <Outlet /> in this component to render the content for the child route components.
src\components\routes\PostList.js
import { Link, useLoaderData } from "react-router"; const PostList = () => { const postData = useLoaderData(); return( <> <h2 className="text-info-emphasis text-center">Posts</h2> <ul className="list-group"> {postData.map((post) => <li className="list-group-item" key={post.id}> {post.id} <Link to={post.id.toString()}>{post.title}</Link> </li> )} </ul> </> ) } export default PostList export async function loader(){ const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10'); // check for any error if(!response.ok){ // use Response object throw new Response("Failed to load data", { status: response.status }); }else{ const responseData = await response.json(); return responseData; } }
Some of the points to note here-
- In the component, loader function named loader is written.
- Uses fetch API to get data from the given URL. Only 10 posts are fetched.
- If there is no error in fetching data (response is ok) then you can return data directly with React Router V7.
- Data fetched by the loader function is retrieved by using the useLoaderData() hook.
- Post data is then iterated to print id and title of each post. With each post a Link with its id is also created
src\components\routes\PostDetails.js
import { useLoaderData } from "react-router"; const PostDetails = () => { const postData = useLoaderData(); return( <> <h2 className="text-center">{postData.title}</h2> <div>{postData.body}</div> </> ) } export default PostDetails; export async function loader({request, params}){ const url = "https://jsonplaceholder.typicode.com/posts/"+params.postId const response = await fetch(url); if (!response.ok) { throw new Response('Error while fetching post data', {status:404}); } else{ const responseData = await response.json(); return responseData; } }
Some of the points to note here-
- In the component, loader function named loader is written which is used to fetch data by post Id.
- In loader function you can’t use useParams() hook to get the route parameters. Router passes an object to the loader function that has two properties- request and params.
- Using request you can access the request body, request URL etc. Using params you can access the route path parameters.
- Data fetched by the loader function is retrieved by using the useLoaderData() hook. In this case data is post data for a particular ID.
- Post title and post body are rendered by this component.
PostList Page
Post Detail page
That's all for this topic Data Loader With Dynamic Routes in React. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
You may also like-
No comments:
Post a Comment