Basic Redux Counter Example
This is a simple single page application that uses Redux and NativeBase as the main Libraries.
Find full code here
1. Aim
We aim to create a simple App that has a counter with increment and decrement functionality. The logic is implemented in Redux.
2. Installation
Note:
If you encounter an issue with React Native Router Flux during building your project, it might be due to issue with latest versions of React Native. Check out this issue. You might have to bump down the versions of React Native and React
- SetUp React Native Project
SetUp a React Native project. Refer this for more information about setting up a React Native project. - Installing Libraries
With a React Native project SetUp, We can now install all required Libraries as follows.
a. Redux and react-redux
In your terminal enter the following
npm install redux react-redux --save
b. NativeBase
npm install native-base@2 --save
c. Configure dependencies
react-native link
By the end of Installation, your package.json file should look something like this.
3. Setting Things Up
With all required Libraries installed, we can start with some real coding. In the root of your project create a folder src
. Inside this folder we create three folders namely reducers, actions, components
and one file App.js
.
3.1. Redux Store Setup
We need to create our store inside our App.js
file. If you are unfamiliar with basic Redux concepts, refer this Documentation.
App.js Code
import React, { Component } from 'react';
import allReducers from './reducers/index.js';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import Counter from './components/counter.js';
const store = createStore(allReducers);
export default class App extends Component{
render(){
return(
<Provider store= {store}>
<Counter />
</Provider>
);
}
}
- We are optimistic here while importing
allReducers
fromreducers
folder. createStore
function takes in ourallReducers
object and creates our Store.Provider
component makes the store available throughout our App.
3.2. Redux Reducers Setup
Reducers will return the data needed by our app. Here we simply need a reducer to return the Counter
value.
Create a file countReducer.js
inside reducers
folder.
Code reducers/countReducer.js
let count= 0;
export default function(state=count, action){
switch (action.type) {
case "Increment": count++;
break;
case "Decrement": count--;
break;
}
return count;
}
The reducer defined above will return the always return count value. Increment
and Decrement
action types will manipulate the count value as shown.
We combine all reducers inside index.js
file inside reducers
function.
Code reducers/index.js
import {combineReducers} from 'redux';
import countReducer from './countReducer.js';
const allReducers= combineReducers({
count: countReducer,
});
export default allReducers;
3.3. Redux Actions Setup
We will simply create two actions Increment
and Decrement
.
Code actions/index.js
export function increment(){
return{
type: "Increment"
};
}
export function decrement(){
return{
type: "Decrement"
};
}
3.4. Redux Component Setup
We just need one component here. A counter component.
3.5. Important stuff
In order to be able to use Reducers and actions, we need to use two important functions. Both these functions have extremely simple applications (although the names sound scary enough).
mapStateToProps
=> This function, simply takes your reducer data, that is required, and converts it into a usable Prop. Now we can use the data as a prop. examplethis.props.data
.
General Syntax of mapStateToProps
function mapStateToProps(state){
return{
dataObj : state.reducerName
};
}
Note: Remember how we allotted names to Reducers in the combineReducers
function. We use the same name to call respective Reducer.
matchDispatchToProps
=> This function simply converts our Actions into usable props.
General Syntax of matchDispatchToProps
function matchDispatchToProps(dispatch){
return bindActionCreators({action1: importedAction1, action2: importedAction2}, dispatch)
}
Note: bindActionCreators
function here simply combines our actions into a single object.
Code components/counter.js
import React, { Component } from 'react';
import { Container, Content, Text, Card, Header, Body, Button, Title, CardItem } from 'native-base';
import { increment, decrement } from '../actions/index.js';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
class Counter extends Component{
render(){
console.log(this.props.count);
return(
<Container>
<Header>
<Body>
<Title>Redux Counter</Title>
</Body>
</Header>
<Content padder>
<Card>
<CardItem>
<Text>
{this.props.count}
</Text>
</CardItem>
</Card>
<Button dark bordered onPress= {() => this.props.increment()}>
<Text>Increment</Text>
</Button>
<Button dark bordered onPress= {() => this.props.decrement()}>
<Text>Decrement</Text>
</Button>
</Content>
</Container>
);
}
}
function mapStateToProps(state){
return{
count : state.count
};
}
function matchDispatchToProps(dispatch){
return bindActionCreators({increment: increment, decrement: decrement}, dispatch)
}
export default connect(mapStateToProps, matchDispatchToProps)(Counter);
3.6. Finishing up
Lastly we import our App
in our index.js file.
Code index.js
import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import App from './src/App.js';
export default class ReduxCounter extends Component {
render() {
return (
<App />
);
}
}
AppRegistry.registerComponent('ReduxCounter', () => ReduxCounter);