Steps to Create React Application and Server Setup
Step 1: Create an npm repository using the command:
npm init --y
Step 2: Create a new react client project by using the command:
npx create-react-app client
Step 3: Create a server file in the current directory using the command:
touch server.js
Step 4: Switch to the src folder in the client folder and remove all the files using the following command:
cd client
cd src
rm *
Step 5: Create a pages folder in the src folder
mkdir pages
Step 6: In the src folder create App.js, index.js, and PrivateRoute.js files.
touch App.js index.js PrivateRoute.js
Step 7: In the pages folder create Home.js Admin.js files.
cd pages
touch Home.js Admin.js
Step 8: Install Axios and react-router-dom in the client folder
npm i axios react-router-dom
The dependencies in package.json file in client directory
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.18.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
Step 9: Install express and cors in the server-side
npm i express cors
The dependencies in package.json file in server
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2"
}
Project Structure:
Example: This example implements the Client Side application creating Home, Admin pages and PrivateRoute component.
Javascript
// Filename - client/src/App.js // Importing the required modules import { BrowserRouter as Router, Routes, Route, Link, } from "react-router-dom" ; import Home from "./pages/Home" ; import Admin from "./pages/Admin" ; import PrivateRoute from "./PrivateRoute" ; import { useEffect, useState } from "react" ; const App = () => { // useState hook to keep track of the login state const [login, setLogin] = useState(() => { // Used local storage to sustain the login state if (!localStorage.getItem( "login" )) { localStorage.setItem( "login" , "false" ); return false ; } return JSON.parse(localStorage.getItem( "login" )); }); // Updating the local storage whenever // the login state changes useEffect(() => { localStorage.setItem( "login" , JSON.stringify(login) ); }, [login]); // Click Handler updates the login state // when the button is clicked const click = () => { setLogin((prev) => { return !prev; }); }; return ( <div className= "App" > <Router> <button onClick={() => click()}> {login ? "Logout" : "Login" } </button> <Link to={ "/admin" }>Admin</Link> <Link to={ "/" }>Home</Link> <Routes> <Route path= "/" element={<Home />} /> { /* Protecting the Admin Page */ } <Route path= "/admin" element={ <PrivateRoute login={login}> <Admin /> </PrivateRoute> } /> </Routes> </Router> </div> ); }; export default App; |
Javascript
// Filename - client/src/pages/Home.js const Home = () => { return ( <div className= "home" > <h1>This is the Home page</h1> </div> ); }; export default Home; |
Javascript
// Filename - client/src/pages/Admin.js const Admin = () => { return ( <div> <h1>Admin Page</h1> </div> ); }; export default Admin; |
Javascript
// Filename - client/src/PrivateRoute.js // Importing the required libraries import { Navigate } from "react-router-dom" ; import { useEffect, useState } from "react" ; const axios = require( "axios" ); // Private Route Component // Params: login -> indicates the login state // children -> the child components of private route const PrivateRoute = ({ login, children }) => { // Authentication Handler const authenticate = (login) => { setLoading( true ); // HTTP Post Request axios({ method: "post" , url: "http://localhost:8000/admin" , data: { logged: login, }, }) .then(({ data }) => { if (data.success) { setAuth( true ); } else { setAuth( false ); } console.log(data.message); setLoading( false ); }) . catch ((error) => { console.log(error); setLoading( false ); }); }; // useState hook to inform the user about the loading state const [loading, setLoading] = useState( true ); // useState hook to authorize the user const [auth, setAuth] = useState( false ); // Authenticates the user whenever the // login state changes useEffect(() => { authenticate(login); return () => { setLoading( true ); }; }, [login]); // If authenticated loads the required component // else redirects to the home page return loading ? ( <h1>Loading...</h1> ) : auth ? ( children ) : ( <Navigate to= "/" /> ); }; export default PrivateRoute; |
Example : This example implements server with middleware using express and cors packages Creating the server and listening to incoming requests on port 8000. We have created a middleware function to authenticate the user. This middleware function can be applied to any route.
Javascript
// Filename - server.js // Importing the required modules const express = require( "express" ); const cors = require( "cors" ); // Creating an express server const app = express(); // Middleware to parse the data into JSON app.use(express.json()); // Middleware to accept requests from localhost:3000 app.use( cors({ origin: "http://localhost:3000" , credentials: true , }) ); // Middleware Function to authenticate the user const auth = (req, res, next) => { console.log(req.body); if (req.body.logged) { next(); return ; } res.send({ success: false , message: "Unauthorized Access" , }); }; // Post request handler for the /admin route app.post( "/admin" , auth, (req, res) => { res.send({ success: true , message: "Successfully Authenticated" , }); }); app.listen(8000, () => { console.log( "Listening on port 8000" ); }); |
Steps to run the application: Run the following command in the client folder
npm start
Run the following command in the base directory
node server.js
Output: This output will be visible on the http://localhost:3000/ on the browser window.
How to prevent access to admin pages using Node.js and React.js ?
To prevent access to admin pages using Node.js and React.js is a common task to avoid unauthorized access. In many websites, the content available to the end-user is limited until he/she proves his/her authenticity by logging in. During the development of MERN Stack Applications, when the server is linked to the client, we may want to limit the pages accessed by the user unless he is logged in.