Build Maps and Save Locations , by using React Native-Redux-Navigation-Icons-MAPs — Part-II

Check Part-I

Hasan Dader
9 min readApr 15, 2019

Welcome to the second part of this article.

In the previous part I made an introduction about the application, then I created the list where the user’s places are displayed, and to create that list I created two components one for the item container and the other is a scroll list where I used FlatList for that purpose. In the same time I showed how to use react-native-vector-icons library. And I finished that part with explanation of react-native-navigation library, how to install and use it.

This part will be about Redux, What is it? How to install it? How does it work? And how did I use it in the app?

So let’s dive in…

1. Redux :

“Simplify state management”

In a react native app we use state in the different classes. In that state we can declare different variables to use them at that specific class, so variables in the state are private and can not be used outside that class. It means in the same app we have different states in the different classes, but some times we need to pass a specific variable/variables from one class to another or modify some variables that exist in a different screen. So to make that work simple and not to have so many states in one app which make using them complex when the app grows up we use Redux.

What redux does is put all state in one place and allow different screens at the app to reach that state. So the state become global. Let’s say it in a different way, imagine a class having some functions, if we declare a variable in one of these functions the others won’t see it, but if we declare that variable outside those functions as a global variable then all functions would see it and be able to use it. Exactly the same thing redux does, it put the state in a place that all screens can reach and so use it.

Redux

By looking at the above image we see the redux general structure.

It consists of a central store where the state exists. To reach the store from any component or class we need to dispatch an action. We can say that the action is a message we send to the store to say I want to do something to the store, this can be adding some data, deleting, updating or anything else we generally do with variables. So actions are predefined information packages.

Then actions reaches the reducers. What do the reducers do? Well, a reducer receives the actions and then updates the state, it does that by running a pure synchronous function where you don’t have any side effects; side effects would be things like reaching out to the web, or loading a different page etc. So the reducer work is to update the central store.

The last point in this redux circle is that when the central store is updated it triggers some automatic subscriptions, then when the components or classes are connected to the redux those subscriptions pass the updated state to them.

Redux in points :

  1. Central Store,
  2. Reducers,
  3. Actions.

Well, simply that was the redux, easy, right! 🤓

2. Installing Redux :

Installing redux is more than easy. All what you need to do is to type the following in the terminal,

npm install --save react-redux

then this,

npm install — save redux

after installing is finished you can say that you got the redux 🤩

3. Using Redux In The App :

This is the part related to redux in our app structure. I created a folder called store and inside that folder I created actions folder, in that folder I’m going to define the actions that I’ll use in the app. And then I created reducers folder, that reducer will update the store as I explained earlier, and exactly in that folder our state will reside. And finally, I create a .js file called configureStore which is the store. So now we have our store, reducers, and actions.

Let’s start from actions folder,

It consists of three .js files.

First one is actionTypes.js where we declare actions that we will use in the app. Remember that in our app what the user do is saving places or removing them. According to that, we need to create two actions one to add places to the store and the other is to delete specific places from the store. Let’s look at the code,

export const ADD_PLACES = 'ADD_PLACES';
export const DELETE_PLACE = 'DELETE_PLACE';

Woow! what a simple code right!

Declaring an action take the form you see above, and be careful that the name of the action before and after the equal sign must be the same. And we say export in the head of the code line because we will call that action in another place.

Now let’s move to locations.js file. In that file we define functions for each action which says what the action will be doing. So let’s look at the code,

import { ADD_PLACES, DELETE_PLACE } from './actionTypes';export const addPlaces = (placeName, location) => {
return {
type: ADD_PLACES,
placeName: placeName,
location: location
};
};
export const deletePlaces = (key) => {
return {
type: DELETE_PLACE,
key: key
};
};

First thing, you remember that I told you that we write export when declaring actions because we call them in another place, here we call them to define functions for them, we called them by the import keyword from the file where we’ve declared them. Each function returns a javascript object, that why we write return { … }. When declaring functions for the actions each function must contain at least the action type, as you see both functions above have the type property. Let’s look at the functions declared for ADD_PLACES action, in the first we write export for the same reason I’ve said before, then const keyword, then the function name which preferred to be a related name here I gave it the name addPlaces. Because the action ADD_PLACES gets the place name and the location from the user here the function should have two parameters for each of these information. Then inside the function we return a javascript object, which contains the action type, and the coming parameters. As you see the parameters are assigned to some variables. We will see how we use these variables latter on. The same thing we do with the second action, but for that action we only get one parameter which is key this is the key of the item the user want to delete.

Let’s look at the last file in actionTypes folder, index.js.

As you see we have two files to declare the actions. Well, when we want to trigger an action to which file we have to go? Actually we need to reach actionTypes.js and locations.js files, but trying to reach them each time we want to trigger an action is not simple, so that we create an index to keep our actions in it. Let’s look at its code to understand better,

export { addPlaces, deletePlaces } from './locations';

what do you say! 😁, index file is this much. What we do is to bind it to the locations.js file and as you know locations.js file is bind to actionTypes.js file, so in this way by reaching index.js file we are actually reach the two other files, and we can think the actions as one piece so we can trigger any action easily.

Now we can move to reducers folder, which structure is like following,

it contains only one file called locations.js.

In this file we keep the state. And as you remember from the previous explanation actions reaches the reducers, so this file will be waiting for one of our actions that we’ve created to update the state according to that action. Let’s look at the code,

import { ADD_PLACES, DELETE_PLACE } from '../actions/actionTypes';const initialState = {
locations: []
};
const reducer = (state = initialState, action) => {
switch(action.type) {
case ADD_PLACES:
return {
...state,
locations: state.locations.concat({
placeName: action.placeName,
location: action.location,
key: Math.random()
})
};
case DELETE_PLACE:
return {
...state,
locations: state.locations.filter(location => {
return location.key !== action.key;
})
};
default:
return state;
}
};
export default reducer;

look at the beginnings of the code and you’ll see our state called “initialState”

and it is very small where it has only one array to keep place details. After that we declare the reducer function, which I said will be waiting for an action, waiting an action means that it uses switch…case , where it will be saying in the case you receive ADD_PLACES action do the following, and in the case you receive DELETE_PLACE action do the following, but in the case you don’t receive any action leave the state as it is, because what the reducer does when receiving an action is updating the state according to that action.

Let’s have a look at what the reducer does when it receives the ADD_PLACES action. First it keeps the previous state as it is by typing …state, . Then it says add to the locations array the coming placeName and location and then it generate a random key to that specific place to be able to reach it when needed.

Note: generating a random key is not a good idea but I used it here just to show you the general logic.

Let’s take one of the passed argument to understand how we pass them and let it be the placeName,

placeName: action.placeName,

we say action.placeName which mean get the placeName that was passed to the action file, and remember that we gave placeName to that variable in the action file and if we had given it another name we would write that other name here, i.e let the name at action file be nameOfPlace here we would call it like this,

placeName: action.nameOfPlace,

if you go back to locations.js file you will see the variables I’m talking about.

I hope you could understand this point.

About the second action DELETE_PLACE what we trying to do here is to find the place which key is equal to the key coming from the action file and remove it from the array. The action file get the item key from the list screen where the places are displayed, where the user press the delete button and that sends the key of that button to the action file and then to reducer file to delete that place. That is the logic of sending data to the reducer.

Now the last file at store folder, which is configureStore.js, I have said that this file is the store.

We bind the reducer to this file to be the reference to the app. I mean when a screen want to reach the redux it should go through this file. Well, how do we bind the reducer to this store? This is what we can see through this code,

import { createStore, combineReducers } from 'redux';import locationsReducer from './reducers/locations';const rootReducer = combineReducers({
locationsList: locationsReducer
});
const configureStore = () => {
return createStore(rootReducer);
};
export default configureStore;

First thing we import createStore and combineReducers from redux “the lib we have installed”, createStore from its name it is for creating the store, and combineReducers is to combine the different reducers if exist, but here we don’t have more than one. Then we import our reducer, our reducer here is locations.js file, we imported it an gave it this name locationsReducer, if we had other reducers we would import them in the same way and then combine them using combineReducers function. After that we create our configureStore function where we tell the redux what our reducer will be.

Well, till here I can tell you that we created the redux for our app.

So, in this part we understood redux, and installed it, and we saw how to create actions and reducers, and finally how to create the store.

In the next part we’ll start to create the screens, so we’ll see how react-native-navigation lib is used and how we bind those screens to the redux.

Remember: Full code and final working app will be published with you in the final part.

Don’t miss the next part … 😄👇🏻

Here is Part-III link … 👈🏻

--

--

Hasan Dader

Seasoned Senior React Native Developer. Passionate about innovation and delivering high-quality mobile solutions.