Redux is basically make the states available throughout the app lifecycle. Let’s take this simple state from a screen. Then we will convert it into Redux.
class MainScreen extends Component {
state = {
counter: 1
}
increaseCounter = () => {
this.setState({counter: this.state.counter + 1});
}
descreaseCounter = () => {
this.setState({counter: this.state.counter - 1});
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={ ()=> this.increaseCounter() }>
<Text>Plus</Text>
</TouchableOpacity>
<Text>{this.state.counter}</Text>
<TouchableOpacity onPress={ ()=> this.descreaseCounter() }>
<Text>Minus</Text>
</TouchableOpacity>
</View>
);
}
}
We will add some of these dependancies:
$ yarn add redux
$ yarn add react-redux
Store – holds our states ( only one state per app ).
Actions – objects that want to change the state inside store.
Dispatcher – dispatching an action to the reducer.
Reducer – receives the action and modifies the state to give us a new state. * pure functions * only mandatory argument is ‘type’.
Subscriber – listen for state change to update the UI via connect
.
At the src/App.js
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import * as types from './redux/types'
const initialState = {
counter: 0
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case types.INCREASE_COUNTER:
return { ...state, counter : state.counter + 1}
case types.DECREASE_COUNTER:
return { ...state, counter : state.counter - 1}
}
return state;
}
const store = createStore(reducer);
class App extends Component {
render() {
return (
<Provider store={store}>
<HomeNavigator/>
</Provider>
);
}
}
We put our constant into a new file at src/redux/types.js
export const INCREASE_COUNTER = 'INCREASE_COUNTER'
export const DECREASE_COUNTER = 'DECREASE_COUNTER'
At the src/screens/MainScreen.js File.
import { connect } from 'react-redux'
import * as types from '../redux/types'
function mapStateToProps(state){
return {
counter: state.counter
}
}
function mapDispatcherToProps(dispatch){
return {
increaseCounter: ()=> dispatch({type: types.INCREASE_COUNTER}),
decreaseCounter: ()=> dispatch({type: types.DECREASE_COUNTER}),
}
}
export default connect(mapStateToProps, mapDispatcherToProps)(MainScreen);
Full code
import React, { Component } from 'react';
import {
View,
Text,
TouchableOpacity
} from 'react-native';
import redux, { createStore } from 'redux';
import { connect } from 'react-redux';
class ReduxScreen extends Component {
render() {
return (
<View style={styles.container}>
<View style={{ flexDirection: 'row', width: 300, justifyContent:'space-around'}}>
<TouchableOpacity onPress={()=>this.props.decreaseCounter()}>
<Text style={{fontSize: 40,fontWeight:'800'}}>-</Text>
</TouchableOpacity>
<Text>{this.props.counterABC}</Text>
<Text>{this.props.counter2}</Text>
<TouchableOpacity onPress={()=>this.props.increaseCounter()}>
<Text style={{fontSize: 40,fontWeight:'800'}}>+</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
function mapStateToProps(state) {
return {
counterABC: state.counter,
counter2: state.counter2,
}
}
function mapsDispatchToProps(dispatch){
return {
increaseCounter: () => dispatch({type:'INCREASE_COUNTER'}),
decreaseCounter: () => dispatch({type:'DECREASE_COUNTER'})
}
}
const styles = {
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
};
export default connect(mapStateToProps,mapsDispatchToProps)(ReduxScreen);