React Router Authentication
We will cover protected routes and authentication using react-router in React applications.
When building commercial web applications or websites in React, we often need to hide certain routes in the application from users who are not logged in or do not have a specific user role required to access those routes.
React Router provides us with protected routes; they let us choose which routes a user can access based on their role or whether they are logged in.
For example, we have a page that is accessible to all users home
, about
such as , , contact
and login
. But protected routes such as 仪表板
and 配置文件设置
can only be accessed by logged in users.
React Router doesn't provide any functionality for this, but adding this functionality is pretty simple and straight forward. First, we need to add functionality to authenticate users to start working with protected routes.
We will use a fake AuthUser
Hook to check the authentication status.
Let us create a new application using the following command.
# react
npx create-react-app my-app
After creating our new application in React, we will go to our application directory using this command.
# react
cd my-app
Now, let's run our application to check if all dependencies are installed correctly.
# react
npm start
We will src
create a new file in the folder AuthUser.js
. Once we have created a new file, we will now create a context and assign it to a constant authUserContext
.
# react
const authUserContext = React.createContext();
Once we have created a context, we will now create a function AuthUser
that will set the state of two variables to true authenticate
and setAuthenticate
false, which we will use to check if the user is authenticated.
We'll create 2 methods that return login()
and logout()
. login()
will setAuthenticate
set the value of to true, and logout()
will set it back to false.
Now, we will export the function AuthenticationProvider
, which will AuthUser()
be saved in a constant auth
. So our AuthUser.js
code in will be as follows.
import * as React from "react";
const authUserContext = React.createContext();
function AuthUser() {
const [authenticate, setAuthenticate] = React.useState(false);
return {
authenticate,
login() {
return new Promise((res) => {
setAuthenticate(true);
res();
});
},
logout() {
return new Promise((res) => {
setAuthenticate(false);
res();
});
}
};
}
export function AuthenticationProvider({ children }) {
const auth = AuthUser();
return (
<authUserContext.Provider value={auth}>{children}</authUserContext.Provider>
);
}
export default function AuthenticateConsumer() {
return React.useContext(authUserContext);
}
Whenever we want to use authenticate
, , login()
and logout()
, we can use AuthUser
Hooks. We will start building the navigation, which will contain 5 components Home
, About
, Profile
, Login
, and Dashboard
.
Home
, About
and Login
will be publicly accessible, while Dashboard
and Profile
will only be accessible if the user is authenticated.
First, we'll react-router-dom
import Link
, Routes
, Route
, UseNavigate
and from userLocation
. We'll also import from the new file we created AuthUser
.
# react
import * as React from "react";
import {
Link,
Routes,
Route,
useNavigate,
Navigate,
useLocation
} from "react-router-dom";
import AuthUser from "./AuthUser";
Now we'll define constants for the navigation that appears when one of the navigation links is visited.
If it is a publicly accessible link, the public route will be displayed, if it is a private link, the private route will be displayed only if the user is authenticated. Otherwise, it will be redirected to the login page.
# react
const Home = () => <h1>Home (Public Route)</h1>;
const About = () => <h1>About (Public Route)</h1>;
const Dashboard = () => <h1>Dashboard (Private)</h1>;
const Profile = () => <h1>Profile (Private)</h1>;
Now we'll Login
create a constant for the method, where we'll log the user in and redirect them to after authentication dashboard
.
If the user is not logged in, it returns a login page content which will be displayed whenever an unauthenticated user tries to access a private page.
const Login = () => {
const navigate = useNavigate();
const { login } = AuthUser();
const { state } = useLocation();
const handleLogin = () => {
login().then(() => {
navigate(state?.path || "/dashboard");
});
};
return (
<div>
<h1>Login</h1>
<button onClick={handleLogin}>Log in</button>
</div>
);
};
Now we will create a navigation function in which we will return a navigation bar with all the routes, both public and private, with a login button if the user is not authenticated and a logout button if the user is authenticated.
We will also create 2 methods, handleLogout
and handleLogin
.
function Nav() {
const { authenticate, logout, login } = AuthUser();
const navigate = useNavigate();
const handleLogout = () => {
logout();
navigate("/");
};
const handleLogin = () => {
login();
navigate("/dashboard");
};
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>{!authenticate && <button onClick={handleLogin}>Login</button>}</li>
</ul>
{authenticate && <button onClick={handleLogout}>Logout</button>}
</nav>
);
}
We will create a function RequireAuthentication
that will authenticate the user whenever they try to access a private route.
function RequireAuthentication({ children }) {
const { authenticate } = AuthUser();
const location = useLocation();
return authenticate === true ? (
children
) : (
<Navigate to="/login" replace state={{ path: location.pathname }} />
);
}
In our App()
function, we will define our routes.
export default function App() {
return (
<div>
<Nav />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route
path="/dashboard"
element={
<RequireAuthentication>
<Dashboard />
</RequireAuthentication>
}
/>
<Route
path="/profile"
element={
<RequireAuthentication>
<Profile />
</RequireAuthentication>
}
/>
<Route path="/login" element={<Login />} />
</Routes>
</div>
);
}
Let's test our application and check how it works. See the demo here .
Output:
As you can see in the example above, it's pretty easy to set up authenticated routes, but the AuthUser
Hook we're using is just a frontend check.
However, if we are developing a proper web application, we need to authenticate users on the backend to protect our system.
For reprinting, please send an email to 1244347461@qq.com for approval. After obtaining the author's consent, kindly include the source as a link.
Related Articles
How to reverse an array in React
Publish Date:2025/03/13 Views:198 Category:React
-
在 React 中反转数组:使用扩展语法 `(...)` 创建数组的浅表副本。在副本上调用 `reverse()` 方法。将结果存储在变量中。
Setting data attributes in React
Publish Date:2025/03/13 Views:84 Category:React
-
要在 React 中为元素设置 data 属性,请直接在元素上设置属性,例如 或使用 setAttribute() 方法,例如 el.setAttribute('data-foo', 'bar')。 我们可以访问事件对象上的元素或
Toggle a class on click in React
Publish Date:2025/03/13 Views:153 Category:React
-
要在 React 中单击时切换类:在元素上设置 onClick 属性。将活动状态存储在状态变量中。使用三元运算符有条件地添加类。
Sorting an array of objects in React
Publish Date:2025/03/13 Views:77 Category:React
-
在 React 中对对象数组进行排序: 创建数组的浅拷贝。 调用数组的 `sort()` 方法,传递给它一个函数。 该函数用于定义排序顺序。
Generate a random number in React
Publish Date:2025/03/13 Views:189 Category:React
-
使用 Math.random() 函数在 React 中生成一个随机数,例如 Math.floor(Math.random() * (max - min + 1)) + min。 Math.random 函数返回 0 到小于 1 范围内的数字,但也可用于生成特定范围内的数字。
Open links in new tabs with React
Publish Date:2025/03/13 Views:76 Category:React
-
要在 React 的新选项卡中打开链接,请使用 a 元素并将其 `target` 属性设置为 _blank,例如 。 _blank 值表示资源已加载到新选
How to set target=_blank in React
Publish Date:2025/03/13 Views:199 Category:React
-
要在 React 中将元素的目标属性设置为 _blank,请使用锚元素并设置 rel 属性,例如 。 _blank 值表示资源已加载到新选项卡中。
Showing hover elements in React
Publish Date:2025/03/13 Views:177 Category:React
-
要在 React 中显示悬停元素:在元素上设置 `onMouseOver` 和 `onMouseOut` 属性。 跟踪用户是否将鼠标悬停在状态变量中的元素上。 根据状态变量有条件地渲染其他元素。
Passing components as props in React
Publish Date:2025/03/13 Views:164 Category:React
-
我们可以使用内置的 children 属性在 React 中将组件作为属性 props 传递。 我们在组件的开始标签和结束标签之间传递的所有元素都会分配给 children 属性。