DEV Community

Srivasthava12
Srivasthava12

Posted on

React Authentication App Using Redux And Sagas

Overview

The things that I am going to go through in this post are:

We will be visiting the above-mentioned points while we are working on our Auth app.
Let's establish the fact that Redux is not related to React. Redux can be used in Angular too. Said that, Redux gels with React impeccably. So, let me answer the question what is redux?
To keep it simple Redux is “open-source JavaScript library for managing application state”. It helps you write applications that behave consistently.

To spice this up let’s use real API’s. You can use the backend API service that I have in my repo i.e.., Authentication with Node and follow the instructions mentioned in README file to run the service or you could use your own json web token based API.

Let the show begin!!

Alt Text

To start the show we have to stage our react app. To do so follow the commands.

Make sure you have create-react-app installed
a) $ npm install -g create-react-app

Create react app
b) $ npx create-react-app my-app

Move into the directory my-app
c) $ cd my-app

Run the react app
d)$ npm start

Let's install all the required pacakges
e)$ npm i redux react-redux redux-saga react-router redux-form --save

Now you have staged your react app. So, let's dive in.

In code directory. The rundown of the structure is given below:

src/ login/ actions.js constants.js sagas.js selector.js reducer.js index.js components/ login.js register/ actions.js constants.js sagas.js selector.js reducer.js index.js components/ register.js user/ reducer.js actions.js constants.js share/ Messages.js helpers/ api-errors.js check-auth.js Main.js index-reducer.js index-sagas.js 
Enter fullscreen mode Exit fullscreen mode

Let's go throught the folder and files we have just created:
login/, register/ & user/
login/ & register/ are the routes that we are going to use.

Now coming to the files that we created:
a) actions.js are payloads of information that send data from your application to your store. They are plain Javascript object
b) reducer.js specify how the application's state changes in response to sent to the store.
c) constants.js the place where we will have our constants for actions and reducers
d)sagas.js this is where we manage the impure operations i.e. asynchronous things like data fetching
e) index-reducer.js & index-sagas.js are the hub where we combile all reducers and sagas

let's go into the code

1) In the directory src/index

  • The whole code for index.js is:
import React from 'react'; import ReactDOM from 'react-dom'; import { applyMiddleware, createStore, compose } from 'redux'; import { Provider } from 'react-redux'; import createSagaMiddleware from 'redux-saga'; import { routerMiddleware } from 'react-router-redux'; import { history } from './history'; import { Router } from 'react-router-dom'; // Import all of our components import App from './App'; import './index.css'; // Import the index reducer and sagas import IndexReducer from './index-reducer'; import IndexSagas from './index-sagas'; import registerServiceWorker from './registerServiceWorker'; // Setup the middleware to watch between the Reducers and the Actions const sagaMiddleware = createSagaMiddleware(); const routersMiddleware = routerMiddleware(history); /*eslint-disable */ const composeSetup = process.env.NODE_ENV !== 'production' && typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose; /*eslint-enable */ const store = createStore( IndexReducer, composeSetup(applyMiddleware(sagaMiddleware, routersMiddleware)) // allows redux devtools to watch sagas ); // Begin our Index Saga sagaMiddleware.run(IndexSagas); ReactDOM.render( <Provider store={store}> <Router history={history}> <App /> </Router>  </Provider>  document.getElementById('root') ); registerServiceWorker(); 
Enter fullscreen mode Exit fullscreen mode
  • Now let's go throught the above boiler code
 import React from 'react'; import ReactDOM from 'react-dom'; import { applyMiddleware, createStore, compose } from 'redux'; import { Provider } from 'react-redux'; import createSagaMiddleware from 'redux-saga'; import { routerMiddleware } from 'react-router-redux'; import { history } from './history'; import { Router } from 'react-router-dom'; // Import all of our components import App from './App'; import './index.css'; // Import the index reducer and sagas import IndexReducer from './index-reducer'; import IndexSagas from './index-sagas'; 
Enter fullscreen mode Exit fullscreen mode
import the required pakages 
Enter fullscreen mode Exit fullscreen mode
  • Middleware

    const sagaMiddleware = createSagaMiddleware() const routersMiddleware = routerMiddleware(history); 

Creates a Redux middleware and connects the Sagas to the Redux Store

  • Creating a Store

    /*eslint-disable */ const composeSetup = process.env.NODE_ENV !== 'production' && typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose /*eslint-enable */ 

const store = createStore(
IndexReducer,
composeSetup(applyMiddleware(sagaMiddleware, routersMiddleware)),
)

 Here ` composeSetup(applyMiddleware(sagaMiddleware, routersMiddleware)),` allows redux to watch sagas and router + To Start the Saga middleware ```javascript sagaMiddleware.run(IndexSagas) 
Enter fullscreen mode Exit fullscreen mode

Can run only after the applyMiddleware phase.

  • Now let's Render the Index.js
 ReactDOM.render( <Provider store={store}> <Router history={history}> <App /> </Router>  </Provider>,  document.getElementById('root') ); registerServiceWorker(); 
Enter fullscreen mode Exit fullscreen mode

So here we are Providing react app with a store, get it providing store <Provider store={store}>

2) Now let's get into index-reducer.js

 ```javascript import { combineReducers } from 'redux' import { reducer as form } from 'redux-form' const IndexReducer = combineReducers({ form }) export default IndexReducer ``` 
Enter fullscreen mode Exit fullscreen mode

The combineReducers helper function turns an object whose values are different reducing functions into a single reducing function you can pass to createStore

3) Lets get in to index-saga.js

import { all } from 'redux-saga/effects'; export default function* IndexSaga() { yield all([ ]); } 
Enter fullscreen mode Exit fullscreen mode

4) Now that we have done with indexes of the reducers, saga and the main Index lets get in to App.js :

import React, { Component } from 'react'; import './App.css'; import Main from './Main'; class App extends Component { render() { return ( <div className="App"> <Main /> </div>  ); } } export default App; 
Enter fullscreen mode Exit fullscreen mode

Here in App, <Main /> is where our routes exist

5) We have separated a component to deal with the routes of the application i.e. the Main Component

import React from 'react'; import { Switch, Route } from 'react-router-dom'; import Login from '../src/login'; import Register from '../src/register'; export default class Main extends React.Component { render() { return ( <main> <Switch> <Route path="/login" component={Login} />  <Route path="/register" component={Register} />  </Switch>  </main>  ); } } 
Enter fullscreen mode Exit fullscreen mode

Let's dig in,
Switch
<Switch> is unique in that it renders a route exclusively. In contrast, every <Route> that matches the location renders inclusively.

Top comments (0)