React - React Router v6
React Router is a popular library for declarative routing in React web applications. It allows you to define routes as components and navigate between them using links or programmatic logic. React Router has recently released its latest version, v6.22.1, which introduces some exciting new features and improvements. In this article, I will give you an overview of what’s new in React Router v6 and how you can use it in your projects.
Feature Overview
React Router v6 has a lot of changes from the previous version, but here are some of the highlights:
Getting Started
To start using React Router v6 in your project, you need to install the react-router-dom package from npm:
npm install react-router-dom
领英推荐
Then, you need to import the components and hooks you need from the package:
import { BrowserRouter, Routes, Route, Link, useNavigate, useLoaderData, useNavigation } from 'react-router-dom';
You can then use the BrowserRouter component to wrap your app and provide the routing context. You can use the Routes component to define your routes as nested components. You can use the Route component to specify the path, element, loader, action, and errorElement props for each route. You can use the Link component to create navigation links to your routes. You can use the useNavigate hook to perform navigation actions programmatically. You can use the useLoaderData hook to access the data fetched by the loader prop. You can use the useNavigation hook to access the navigation object.
Here is a simple example of how to use React Router v6 in your app:
import React from 'react';
import { BrowserRouter, Routes, Route, Link, useNavigate, useLoaderData, useNavigation } from 'react-router-dom';
// A component that fetches some data from an API
function fetchData() {
return fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json());
}
// A component that renders a list of posts
function Posts() {
// Get the data from the loader prop
let data = useLoaderData();
// Get the navigation object
let navigation = useNavigation();
// Get the navigate function
let navigate = useNavigate();
// Render the posts
return (
<div>
<h1>Posts</h1>
<ul>
{data.map(post => (
<li key={post.id}>
<Link to={`/posts/${post.id}`}>{post.title}</Link>
</li>
))}
</ul>
<button onClick={() => navigate('/create')}>Create Post</button>
{/* Show a message if the navigation type is replace */}
{navigation.type === 'replace' && <p>Post created successfully!</p>}
</div>
);
}
// A component that renders a single post
function Post() {
// Get the data from the loader prop
let data = useLoaderData();
// Get the post id from the params
let { id } = useParams();
// Render the post
return (
<div>
<h1>Post {id}</h1>
<p>{data.body}</p>
<Link to="/posts">Back to Posts</Link>
</div>
);
}
// A component that renders a form to create a post
function CreatePost() {
// Get the navigate function
let navigate = useNavigate();
// Handle the form submission
function handleSubmit(event) {
event.preventDefault();
// Get the form data
let formData = new FormData(event.target);
// Create a post object
let post = {
title: formData.get('title'),
body: formData.get('body')
};
// Perform the action prop
navigate('/posts', { action: () => createPost(post) });
}
// A function that creates a post on the server
function createPost(post) {
return fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify(post),
headers: {
'Content-type': 'application/json; charset=UTF-8'
}
})
.then(response => response.json());
}
// Render the form
return (
<div>
<h1>Create Post</h1>
<form onSubmit={handleSubmit}>
<label htmlFor="title">Title</label>
<input id="title" name="title" type="text" required />
<label htmlFor="body">Body</label>
<textarea id="body" name="body" required />
<button type="submit">Submit</button>
</form>
<Link to="/posts">Cancel</Link>
</div>
);
}
// A component that renders an error message
function Error({ error }) {
// Render the error
return (
<div>
<h1>Error</h1>
<p>{error.message}</p>
<Link to="/">Go Home</Link>
</div>
);
}
// The main app component
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Posts />} loader={fetchData} />
<Route path="/posts" element={<Posts />} loader={fetchData} />
<Route path="/posts/:id" element={<Post />} loader={fetchPost} />
<Route path="/create" element={<CreatePost />} />
<Route path="*" element={<Error error={new Error('Page not found')} />} />
</Routes>
</BrowserRouter>
);
}
// A function that fetches a single post from an API
function fetchPost() {
// Get the post id from the params
let { id } = useParams();
// Fetch the post
return fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then(response => response.json());
}
export default App;
Conclusion
React Router v6 is a major update that brings a lot of new features and improvements to the library. It simplifies the API, improves the data fetching, enhances the navigation, and handles the errors better. It also has a lot of other features that I didn’t cover in this article, such as lazy loading, scroll restoration, form handling, and more. You can check out the official documentation for more details and examples.
If you are using React Router v5 or earlier, I highly recommend you to upgrade to React Router v6 and enjoy the benefits of the new version. The migration guide will help you with the process. If you are new to React Router, I hope this article gave you a good introduction to the library and how to use it in your projects.