<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Akpan Akan</title>
    <description>The latest articles on DEV Community by Akpan Akan (@akanstein).</description>
    <link>https://dev.to/akanstein</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F711073%2Faf63020e-85ed-4ecf-84dc-73ab0ffb5125.jpeg</url>
      <title>DEV Community: Akpan Akan</title>
      <link>https://dev.to/akanstein</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akanstein"/>
    <language>en</language>
    <item>
      <title>Protected routes in react with react router and redux</title>
      <dc:creator>Akpan Akan</dc:creator>
      <pubDate>Sat, 02 Oct 2021 06:11:16 +0000</pubDate>
      <link>https://dev.to/akanstein/protected-routes-with-react-router-and-redux-3e62</link>
      <guid>https://dev.to/akanstein/protected-routes-with-react-router-and-redux-3e62</guid>
      <description>&lt;p&gt;Protected routes can only be accessed by authenticated users in an application. React-router and redux have been winning a combination for a lot of SPA(single page applications), but for a newbie, figuring how to combine these two packages to implement a protected route can seem a bit complex. We'll be looking at how to implement protected routes with react-router and redux in a simplified manner.&lt;/p&gt;

&lt;p&gt;We'll assume you are familiar with react. If however, you're unfamiliar with react you can checkout &lt;a href="https://reactjs.org/docs/getting-started.html" rel="noopener noreferrer"&gt;https://reactjs.org/docs/getting-started.html&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  SETUP
&lt;/h4&gt;

&lt;p&gt;We'll start off by spinning up a react app with CRA(create-react-app). To learn more about CRA checkout &lt;a href="https://reactjs.org/docs/create-a-new-react-app.html" rel="noopener noreferrer"&gt;https://reactjs.org/docs/create-a-new-react-app.html&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx create-react-app my-protected-app


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Dependencies
&lt;/h4&gt;

&lt;p&gt;Redux is an open source library for managing state in centralised manner, it is very popular in the frontend community and a must for many dev roles. &lt;/p&gt;

&lt;p&gt;React router provides declarative routing for react. It is the go to library for react SPAs routing.&lt;/p&gt;

&lt;p&gt;Install these dependencies to get going started&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

yarn add react-router-dom redux react-redux
or 
npm install react-router-dom redux react-redux --save


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Setting up our app
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;NB: you can skip this part if your app is already setup&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First we'll create a &lt;code&gt;Home&lt;/code&gt; component.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from "react";

const Home = () =&amp;gt; {
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to my protected route!&amp;lt;/h1&amp;gt;
      &amp;lt;h2&amp;gt;We've got cookies&amp;lt;/h2&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Home;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Home view on browser&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7hgv4cpe7kwff6d8gh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7hgv4cpe7kwff6d8gh1.png" alt="Home page view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we'll create a &lt;code&gt;Login&lt;/code&gt; component from which the user logs in to access the home page.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from "react";

const Login = () =&amp;gt; {

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;div className="login-form"&amp;gt;
        &amp;lt;h4 className="form-title"&amp;gt;Login&amp;lt;/h4&amp;gt;
        &amp;lt;div className="form-control"&amp;gt;
          &amp;lt;input type="text" name="username" placeholder="Username" /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="form-control"&amp;gt;
          &amp;lt;input type="password" placeholder="Enter password" name="password" /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button className="login-btn"&amp;gt;
          Login
        &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Login;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Login view&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpc3lii4hhwrocpd82ltj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpc3lii4hhwrocpd82ltj.png" alt="Login view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we add the &lt;code&gt;style.css&lt;/code&gt; for the app styling.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}

.App {
  font-family: sans-serif;
  text-align: center;
  height: 100vh;
  width: 100%;
}

.login-form {
  width: 450px;
  padding: 20px 25px;
  border-radius: 10px;
  border: solid 1px #f9f9f9;
  text-align: left;
  margin: auto;
  margin-top: 50px;
  background: #b88bf72f;
}

.form-title {
  margin-top: 0;
  margin-bottom: 15px;
  text-align: center;
}

.form-control {
  margin-bottom: 15px;
  width: 100%;
}

.form-control input {
  border-radius: 5px;
  height: 40px;
  width: 100%;
  padding: 2px 10px;
  border: none;
}

.login-btn {
  padding: 5px 10px;
  border-radius: 5px;
  border: none;
  background: rgb(60, 173, 239);
  color: #fff;
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Setting up redux
&lt;/h4&gt;

&lt;p&gt;Let's create &lt;code&gt;store&lt;/code&gt; directory, then a &lt;code&gt;types.js&lt;/code&gt; file in &lt;code&gt;src/store&lt;/code&gt; to export our different store action types&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export const LOGIN_USER = "LOGIN USER";


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, we'll create a &lt;code&gt;store.js&lt;/code&gt; file in our &lt;code&gt;src/store&lt;/code&gt; folder. Here we instantiate our store and it's initial state.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { createStore } from "redux";
import { LOGIN_USER } from "./types";

const intitialState = {
  authenticated: false
};

const reducer = (state = intitialState, action) =&amp;gt; {
  switch (action.type) {
    case LOGIN_USER:
      return { ...state, authenticated: true };

    default:
      return state;
  }
};

const store = createStore(reducer);

export default store;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Our initial state object contains an authenticated state which is false by default, indicating a user is not logged in. We see more on changing this state. Checkout &lt;a href="https://redux.js.org/api/createstore" rel="noopener noreferrer"&gt;createStore&lt;/a&gt; to learn more about setting up redux.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up react-router
&lt;/h4&gt;

&lt;p&gt;In the &lt;code&gt;src/index.js&lt;/code&gt; file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
import App from "./App";

ReactDOM.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;Router&amp;gt;
      &amp;lt;App /&amp;gt;
    &amp;lt;/Router&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;,
  document.getElementById("root")
);



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We import &lt;code&gt;BrowserRouter&lt;/code&gt; and wrap our &lt;code&gt;App&lt;/code&gt; component in it.&lt;/p&gt;

&lt;p&gt;At this point we create our &lt;code&gt;ProtectedRoute&lt;/code&gt; to handle verifying a user is authenticated before rendering the component. If the user is not authenticated we want to redirect them to the login page. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from "react";
import { useSelector } from "react-redux";
import { Redirect, Route } from "react-router-dom";

const ProtectedRoute = ({ path, exact, children }) =&amp;gt; {
  const auth = useSelector((store) =&amp;gt; store.authenticated);

  return auth ? (
    &amp;lt;Route path={path} exact={exact}&amp;gt;
      {children}
    &amp;lt;/Route&amp;gt;
  ) : (
    &amp;lt;Redirect to="/login" /&amp;gt;
  );
};

export default ProtectedRoute;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We check the authenticated state in our redux store and render the component on the condition that it authenticated is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, in our &lt;code&gt;App.js&lt;/code&gt; we add &lt;code&gt;Switch&lt;/code&gt; giving our app ability to switch components between routes. We also bring in our components, our protected route and set up our store in our App component.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from "react";
import "./styles.css";
import { Provider } from "react-redux";
import store from "./store";
import { Route, Switch } from "react-router-dom";
import ProtectedRoute from "./ProtectedRoute";
import Home from "./Home";
import Login from "./Login";

const App = () =&amp;gt; {
  return (
    &amp;lt;Provider store={store}&amp;gt;
      &amp;lt;Switch&amp;gt;
        &amp;lt;Route path="/login"&amp;gt;
          &amp;lt;Login /&amp;gt;
        &amp;lt;/Route&amp;gt;
        &amp;lt;ProtectedRoute exact path="/"&amp;gt;
          &amp;lt;Home /&amp;gt;
        &amp;lt;/ProtectedRoute&amp;gt;
      &amp;lt;/Switch&amp;gt;
    &amp;lt;/Provider&amp;gt;
  );
};
export default App;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Finishing up
&lt;/h4&gt;

&lt;p&gt;To finish things up, we modify our &lt;code&gt;Login&lt;/code&gt; component with the ability to change the state at login.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useHistory } from "react-router";

import { LOGIN_USER } from "./store/types";

const Login = () =&amp;gt; {
  const dispatch = useDispatch();
  const history = useHistory();
  const [inputs, setInput] = useState({ username: "", password: "" });

  function inputChange(e) {
    setInput({ ...inputs, [e.target.name]: e.target.value });
  }

  function login(event) {
    event.preventDefault();
    if (!inputs.username || !inputs.password) return;
    dispatch({ type: LOGIN_USER });
    history.push("/");
  }

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;form onSubmit={login} className="login-form"&amp;gt;
        &amp;lt;h4 className="form-title"&amp;gt;Login&amp;lt;/h4&amp;gt;
        &amp;lt;div className="form-control"&amp;gt;
          &amp;lt;input
            type="text"
            name="username"
            placeholder="Username"
            onChange={inputChange}
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="form-control"&amp;gt;
          &amp;lt;input
            type="password"
            placeholder="Enter password"
            name="password"
            onChange={inputChange}
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button type="submit" className="login-btn"&amp;gt;
          Login
        &amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Login;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We use the &lt;code&gt;useDispatch&lt;/code&gt; hook to dispatch actions to our redux store. Notice we use the &lt;code&gt;LOGIN_USER&lt;/code&gt; type we create in our &lt;code&gt;store/types&lt;/code&gt; in dispatch. We finally round by routing to the home route with the &lt;code&gt;useHistory&lt;/code&gt; from react-router. Now as far as our inputs aren't empty we can login to the home page.&lt;/p&gt;

&lt;p&gt;From here, more can be done to add extra features, congrats on your protected route.&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>routes</category>
      <category>reactrouter</category>
    </item>
  </channel>
</rss>
