React - Redux flow

React - Redux flow
Photo by Lautaro Andreani / Unsplash
Redux Flow

Introduction of Redux Flow

  • Redux is a JavaScript framework for managing state in an application
  • Redux follows one direction flow of data.
  • It starts in the view.View means the item on a screen that a user sees.
  • If a user clicks a button or types something in. This is called an action.
  • When an action happens we need to make sure to change what is displayed to the user.
  • That action is dispatched through a reducer function.
  • The reducer must receive the action object and based on that it will figure out what to change and how to make that change. This is how the state management works in Redux.
  • The reducer then pass new object back to the store.
  • The store holds the state. It then updates the state and gives it to the view to update.

Flow of PingPong Action

  • Create a pingPongActionConstant.js file in actionConstants.js then export the constant Variables to this file. Variables are must be in Upper_case and value is same as variable name. Variable names are unique.
export const CALL_PING_ACTION = 'CALL_PING_ACTION';
export const CALL_PONG_ACTION = 'CALL_PONG_ACTION';
  • Next select the index.js file in actionConstants.js and add
export * from './pingPongActionConstant';
  • Create a file in action and give name as pingPongAction.js. In this file first import the Variables from './actionConstants' then export the action using arrow function syntax to dispatch the type to debugger.
import {CALL_PING_ACTION, CALL_PONG_ACTION} from '../actionConstants';

export const ping = () => dispatch => {
  dispatch({
    type: CALL_PING_ACTION,
  });
};

export const pong = () => dispatch => {
  dispatch({
    type: CALL_PONG_ACTION,
  });
};
  • Create pingPongReducer.js file in reducers and add
import {createReducer} from './reducerUtils';
import {CALL_PING_ACTION, CALL_PONG_ACTION} from '../actionConstants';
import {merge} from 'lodash';

const initialState = {
  ping: false,
  pong: false,
};

const callPing = (state = initialState) => {
  return merge({}, state, {ping: true, pong: false});
};

const callPong = (state = initialState) => {
  return merge({}, state, {ping: false, pong: true});
};

export default createReducer(initialState, {
  [CALL_PING_ACTION]: callPing,
  [CALL_PONG_ACTION]: callPong,
});
  • In this program initialState of both Ping and Pong set to false.
  • Select rootReducer.js file. Add
import pingPongReducer from './pingPongReducer' 
  • And also add state to store
pingPong:pingPongReducer,
  • Creating logic in which when we CALL_PING_ACTION dispatch in debugger then action type is set to CALL_PING_ACTION. And in state at the pingPong(pin) ping:True and pong:False.
  • Create PingPongButton into components/Home folder.
import React from 'react';
import {SafeAreaView, Button, StyleSheet, Text, View} from 'react-native';
import {connect} from 'react redux';
import {selectPingPong} from '../../selectors/pingPongSelector';
import {WHITE_COLOR} from '../../styles/GlobalColors';
import {ping, pong} from '../../actions';
import PropTypes from 'prop-types';

const PingPongComponent = ({pingPong, handlePing, handlePong}) => {
 return (
  <SafeAreaView>
   <View>
    <Text>action screen</Text>
   </View>
   <View>
    <Text>{'' + pingPong.ping}</Text>
   </View>
   <View>
    <Text>{'' + pingPong.pong}</Text>
   </View>
   <View style={styles.ButtonContainer}>
    <View style={styles.ButtonTableRow}>
     <View style={styles.Button}>
      <Button
       onPress={handlePing}
       title="Ping Button"
      />
     </View>
    </View>
   </View>
   <View style={styles.ButtonContainer}>
    <View style={styles.ButtonTableRow}>
     <View style={styles.Button}>
      <Button
       onPress={handlePong}
       title="Pong Button"
      />
     </View>
    </View>
   </View>
  </SafeAreaView>
 );
};

PingPongComponent.propTypes={ 
 handlePing: PropTypes.func.isRequired,
 handlePong: PropTypes.func.isRequired,
};

const mapState = state => {
 const pingPong = selectPingPong(state);
 return {pingPong};
};

const actions = {
 handlePing: ping,
 handlePong: pong,
};

export default connect(mapState, actions) (PingPongComponent);

const styles = StyleSheet.create({ 
 Container: {
  backgroundColor: WHITE_COLOR,
  flex: 1,
 },
 ButtonContainer: {
  width: '100%',
 },
 ButtonTableRow: {
  marginTop: 25,
  marginLeft: '30%',
  marginRight: '20%',
  justifyContent: 'space-between',
  flexDirection: 'row',
  alignItems: 'center',
  textAlignVertical: 'center',
  textAlign: 'center',
  padding: 4,
 },
 homeButton: {
  flex: 1,
  justifyContent: 'center',
  alignItems: 'center'
 },
});
  • Select Home.js file in screen folder and add button using navigation 
<View style={styles. homeButtonContainer}>
 <View style={styles.homeButtonTableRow}>
  <View style={styles.homeButton)>
   <PingPongButton
    onPress={() =>
     navigation.navigate('PingPongComponentNavigation',)
    }
    buttonLabel={'Ping Pong Button'}
   />
  </View>
 </View>
</View>
  • Also import the PingPongButton
import {PingPongButton} from '../../components/Home/PingPongButton';
  • Create PingPongComponent in component folder
  • Navigates the PingPongComponent to the DrawerNavigator.js file
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen
 options={{
  headerTitle: 'Ping Pong',
 }}
 name="PingPongComponentNavigation" 
 component={PingPongComponent}
/>
<Drawer.Screen name="Dashboard" component={Dashboard} />
  • Create PingPongSelector.js files in selectors 
import {createSelector} from 'reselect';

const pingPong = state => state.pingPong;

export const selectPingPong = createSelector (
  pingPong,
  pingPongSelect => pingPongSelect,
);
  • Select index.js file in selector and add
export * from './pingPongSelector';
  • Next Import the pingPongSelector to the pingPongComponent.js file
    </View>
   </View>
  </SafeAreaView>
 );
};

PingPongComponent.propTypes={ 
 handlePing: PropTypes.func.isRequired,
 handlePong: PropTypes.func.isRequired,
};

const mapState = state => {
 const pingPong = selectPingPong(state);
 return {pingPong};
};

const actions = {
 handlePing: ping,
 handlePong: pong,
};

export default connect(mapState, actions) (PingPongComponent);

const styles = StyleSheet.create({ 
 Container: {
  backgroundColor: WHITE_COLOR,
  flex: 1,
 },
 ButtonContainer: {
  width: '100%',
 },
 ButtonTableRow: {
  marginTop: 25,
  marginLeft: '30%',
  marginRight: '20%',
  justifyContent: 'space-between',
  flexDirection: 'row',
  alignItems: 'center',
  textAlignVertical: 'center',
  textAlign: 'center',
  padding: 4,
 },
 homeButton: {
  flex: 1,
  justifyContent: 'center',
  alignItems: 'center'
 },
});

Read more