Most of the time, when designing a website, we want to have a similar scenario:
“There are pages that everyone can access. In contrast, there are pages and resources that only those who have logged in to the system can access, otherwise, their request to access these resources must be returned to the login page.“
In this post, I’m going to use the following tools to implement a simple system similar to the one described.
- Linux
- React Js
- IntelliJ IDE
Our simple system is as follows:
All people can access the home page with the address “/”. On this page, there is a link to the protected page with the address “/protected” that only people who are logged in to the system can access, otherwise by clicking on this link, we will be returned to the login page with the address “/login”.
Let’s get started …
Create a new ReactJs project.
Use these commands to create a new ReactJs project and install the react-router-dom module for this project.
sudo npm install -g create-react-app
create-react-app react-js-router-example
cd react-js-router-example
npm install react-router-dom
Establish a regular structure.
This section is optional and depends on your method of organizing files and folders. I created the following structure for this project.
src
├── App.css
├── App.js
├── App.test.js
├── components
│ ├── app
│ │ └── app.js
│ ├── home-page
│ │ └── home-page.js
│ ├── login-page
│ │ └── login-page.js
│ └── protected-page
│ └── protected-page.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
└── setupTests.js
Note that we need the new files:
- /components/app/app.js
- /components/protected-page/protected-page.js
- /components/home-page/home-page.js
- /components/login-page/login-page.js,
and the following file also changes:
- /src/index.js
Change index.js file and injection new app.js file into it.
Change the /src/index.js file as follows. Note that the /components/app/app.js file is used in it, and also because in the future we want to use props.history, this file uses the <BrowserRouter> tag.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/app/app.js';
import * as serviceWorker from './serviceWorker';
import {BrowserRouter} from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
Prepare /components/app/app.js
The mechanism of login and logout depends on you. In this project, I will set item with the “token” key in local storage for login sign and remove this item for leave sign.
As you can see, access to the links “/” and “/login” is free for everyone. But the address “/protected” is protected using the tag <ProtectedRoute>. The function checks whether the person has already logged in can access this address, otherwise, it will be redirected to the login page.
import React from "react";
import {
Route,
Redirect,
withRouter,
Switch
} from "react-router-dom";
import HomePage from "../home-page/home-page";
import LoginPage from "../login-page/login-page";
import ProtectedPage from "../protected-page/protected-page";
class App extends React.Component {
constructor(props) {
super(props);
this.logIn = this.logIn.bind(this);
this.signOut = this.signOut.bind(this);
}
logIn() {
localStorage.setItem("token", "123");
this.props.history.push("/");
}
signOut() {
localStorage.removeItem("token");
this.props.history.push("/");
}
render() {
return (
<Switch>
<Route
exact
path="/"
render={() => (<HomePage handleLogIn={this.logIn}/>)}
/>
<Route
exact
path="/login"
render={() => (<LoginPage handleLogIn={this.logIn}/>)}
/>
<ProtectedRoute path="/protected">
<ProtectedPage handleSignOut={this.signOut}/>
</ProtectedRoute>
</Switch>
);
}
}
function ProtectedRoute({ children, ...rest }) {
return (
<Route
{...rest}
render={() =>
localStorage.getItem("token") ? (
children
) : (
<Redirect
to={{
pathname: "/login",
}}
/>
)
}
/>
);
}
export default withRouter(App);
Prepare the other pages.
Then prepare the content of the pages home, protected and login. These pages are very simple and have no design on them. They include a text to indicate the current location and a bottom to login and signout, or a link to go to another page.
/components/home-page/home-page.js
import React from "react";
import {Link} from "react-router-dom";
export default class HomePage extends React.Component{
render() {
return (
<div>
<p>This is home page. You can go to protected page if you are login to system.</p>
<ul>
<li>
<Link to="/protected">Protected Page</Link>
</li>
</ul>
</div>
);
}
}
/components/protected-page/protected-page.js
import React from "react";
export default class ProtectedPage extends React.Component{
render() {
return (
<div>
<p>This is main page. You can log out.</p>
<button onClick={() => this.props.handleSignOut()}>Log out</button>
</div>
);
}
}
/components/login-page/login-page.js
import React from "react";
export default class LoginPage extends React.Component{
render() {
return (
<div>
<p>You must log in to view the main page at </p>
<button onClick={() => this.props.handleLogIn()}>Log in</button>
</div>
);
}
}
Finally
I hope this article is useful to you. I would also be happy to hear your feedback on this.