Voting App Using React Redux
Redux provides an easy way to centralize the state of your application. There are three basic properties to know in Redux. Action, Store, Reducer. We will cover all these properties one by one.
The Redux Cycle
(Image Credits https://www.slideshare.net/MihailGaberov/using-react-redux-and-saga-with-lottoland-apis-76296469 )
The redux cycle is composed of Action, Store and Reducers. Action is like a message that we send or dispatch to our central Redux Store. The Store is the central part and it saves the global app state. Reducers calculates the next state ie. they handles the main flow. If any change in state occurs, the reducer will check which action type is triggered and then reducer changes the state for that particular action type.
I have learned about the basic redux flow. I created a voting app which with the help of redux will do comparison between three technologies.
The Basic Directory Structure –
In the above image, there is a src folder which contains the main flow of the application. It has sub-directories such as components, reducers and actions.
In actions folder → index.js
export const voteReact =() => {
return {
type: ‘VOTE_REACT’
}
}
export const voteAngular =() => {
return {
type: ‘VOTE_ANGULAR’
}
}
export const voteVueJs =() => {
return {
type: ‘VOTE_VUEJS’
}
}
The above index.js file contains the action type for three technologies – Angular, React and VueJs.
In reducers→ index.js
const initialState = {
angular : 0,
react: 0,
vuejs: 0
}
export default (state = initialState , action) => {
switch (action.type) {
case ‘VOTE_ANGULAR’:
console.log(‘Vote Angular!’);
return Object.assign({}, state, {
angular:state.angular + 1
})
case ‘VOTE_REACT’:
console.log(‘Vote React!’);
return Object.assign({}, state, {
react: state.react +1
})
case ‘VOTE_VUEJS’:
console.log(‘Vote VueJs’);
return Object.assign({}, state, {
vuejs: state.vuejs + 1
})
default:
return state
}
}
In the above index.js file, the reducer takes 2 arguments (state , action) . So depending upon the type of the action the reducer changes the state and return it to the global store.
In src→ index.js
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import {createStore} from ‘redux’;
import ‘./index.css’;
import App from ‘./App’;
import myApp from ‘./reducers’;
import Results from ‘./components/results’;
import registerServiceWorker from ‘./registerServiceWorker’;
let store = createStore(myApp); // the main store of the application.
function render() {
ReactDOM.render(
<div className=”container”>
<App store={store} />
<hr/>
<Results store = {store}/>
</div>
,
document.getElementById(‘root’));
registerServiceWorker();
}
store.subscribe(render);
render();
This index.js is the file where you initialize the app and call ReactDom.
src→ App.js
import React, { Component } from ‘react’;
import {voteAngular,voteReact,voteVueJs } from “./actions/index”;
import ‘./App.css’;
class App extends Component {
constructor(props) {
super(props);
this.store = this.props.store;
}
handleVoteAngular = () => {
this.store.dispatch(voteAngular());
}
handleVoteReact = () => {
this.store.dispatch(voteReact());
}
handleVoteVueJs = () => {
this.store.dispatch(voteVueJs());
}
render() {
return (
<div>
<div className=”jumbotron” style = {{“textAlign”: ‘center’}} >
<h2>What is your favourite front-end framework in 2017</h2>
<h4>click on the logos below to vote!</h4>
<br/>
<div className=”row” style = {{textAlign: ‘justify’ }}>
<div>
<img src= “angular.png” height = “96” align= “left” alt= “angular” onClick={this.handleVoteAngular}></img>
</div>
<div>
<img src= “react_log.png” height = “96” align = “center” alt= “react” onClick={this.handleVoteReact}></img>
</div>
<div>
<img src= “vuejs.png” height = “96” align = “right” alt= “vueJs” onClick={this.handleVoteVueJs}></img>
</div>
</div>
</div>
</div>
);
}
}
export default App;
The above App.js is the main component of the react application.
Components→ results.js
import React, {Component} from ‘react’;
export default class Results extends Component {
constructor(props) {
super(props);
this.store = this.props.store;
}
votesAngularInPercent() {
if(this.store.getState().angular) {
return (this.store.getState().angular / (this.store.getState().angular + this.store.getState().react + this.store.getState().vuejs) )* 100;
}
else {
return 0;
}
}
votesReactInPercent() {
if(this.store.getState().react) {
return (this.store.getState().react / (this.store.getState().angular + this.store.getState().react + this.store.getState().vuejs) )* 100;
}
else {
return 0;
}
}
votesVueJsInPercent() {
if(this.store.getState().vuejs) {
return (this.store.getState().vuejs / (this.store.getState().angular + this.store.getState().react + this.store.getState().vuejs) )* 100;
}
else {
return 0;
}
}
votesAngularInPercentStyle() {
return {
width: this.votesAngularInPercent()+”%”
}
}
votesReactInPercentStyle() {
return {
width: this.votesReactInPercent()+”%”
}
}
votesVuejsInPercentStyle() {
return {
width: this.votesVueJsInPercent()+”%”
}
}
render() {
return (
<div>
<span className=”label label-danger”> Angular: {this.votesAngularInPercent().toFixed(2)+ ‘%’}</span>
<div className=”progress progress-striped active”>
<div className=”progress-bar progress-bar-danger” style = {this.votesAngularInPercentStyle()} ></div>
</div>
<span className=”label label-danger”> React: {this.votesReactInPercent().toFixed(2)+ ‘%’}</span>
<div className=”progress progress-striped active”>
<div className=”progress-bar progress-bar-danger” style = {this.votesReactInPercentStyle()} ></div>
</div>
<span className=”label label-danger”> VueJs: {this.votesVueJsInPercent().toFixed(2)+ ‘%’}</span>
<div className=”progress progress-striped active”>
<div className=”progress-bar progress-bar-danger” style = {this.votesVuejsInPercentStyle()}></div>
</div>
</div>
)
}
}
The above results.js file contains the component called Result.
All the components of the application will come under the components folder.
The output of the above application –
Thanks for Reading.
Leave a Reply Cancel reply