Instagram with React Native, Firebase & Redux, Part 2

Álvaro Hernández
11 min readAug 16, 2018

--

Hi again!

We are here to continue this amazing serie to build our own Intstagram app!

If you didn’t see the first part, go and take a look! Take me to 1st part.

We defined our architecture, created our first components, reducers and actions and hooked everything with firebase, and got our ‘Login / Signup’ working too! See this preview of what we are building today:

Pretty nice (and scaring… ) but it’s fine, let’s do it!

First of all and very important, if you installed in the last chapter the “react-native-vector-icons”, you need to link it. It’s simple. We usually do this to work with native components (android & iOS), see more info here.

  • rnpm link <package name> / react-native link <package name>

Run now to our firebase console and create a realtime database! It doesn’t matter for now the security we choose.

Now, let’s define our tabbar and the icons!

This is my router component:

find the code in github

Okay, step by step:

  • Create all the components that we are going to use, it doesn’t matter what they render. Just to have them.
  • I created stateless components for each icon, and I liked these, but you are free your own icons or custom images! Icons directory
  • What ‘hideNavBar’ means and why we use it? Well, if you don’t like the header that our router has, we can just hide it an use our own!
  • ‘PanHandlers’? To prevent the user navigate with gestures. Nobody wants to navigate to ‘home’ and accidentally go back to login.
  • Tabs? Why ‘configPost’ is not inside tabs? All we put inside the ‘Tabs’ component are going to be rendered here, and we just want our four navigation tabs:
  • In the ‘addPost’ component the header is hidden because we will use our own header.

And, said that, let’s create our ‘Header’ in our ‘common’ folder:

find the code in github

The header will have two buttons, one for go back, one for go to the next screen and a title, all passed by props. You can customize it as you want!

Now, the images we are going to use are free of copyright. I created a JSON file inside ‘../posts/images/data.json’ with ‘name’ and ‘url’ as key, example:

find the code in github

You can use this images but feel free to use the ones you like.

Our posts will have:

  • Comments (array with all the comments)
  • Comments_number (number of comments)
  • Date
  • Image (url)
  • Liked (true if liked, false if not)
  • Likes (number of likes)
  • Location
  • Title
  • Username (for now will be hardcoded)
  • Userpic (for now will be hardcoded)

Let’s see how a post will be:

Has sense to write this component when we have no way to add a post? Well, we’ll have this feature soon, so let’s make this easy.

We will render our posts in the “Home” component.

Inside the folder ‘post’, create Post.js, and let’s make this component.

We will render each post from a function, something like:

Everytime we create the component ‘Post’, we pass to it all the fields of our post.

This is my Home component, let’s see line by line.

find the code in github
  • ComponentWillMount: this lifecycle hook will fetch our post into our props with the function ‘fecthPosts()’, we’ll make it later.
  • ComponentWillReceiveProps: this is how we deal with async actions. Our component has a set of props, but it doesn’t have all the posts at the moment we render it, thats where this hook plays. We’ll compare our actual props with the next props, if they are different, this means that the nextProps coming has our posts, we’ll set to our state this posts. It’s nextProps.posts.posts because the first posts it’s the name when mapping the state to props, the second posts it’s the name of the property.
  • RenderPosts: now that we have our posts in our state, we can do two things: render if we have at least one post, or give the idea to create one.
  • Why this?
find the code in github

Firebase doesn’t work with arrays, so the data we’ll have it’s a big object with properties, this properties are the keys and the keys have each post. To doesn’t make this to hard to code, ‘arrayPosts’ will have all the posts in an array and ‘keysPosts’ will have all the keys in an array, ordered the same way as the posts.

Now, in our ‘actions’ folder let’s add the type: “POST_FETCH_ALL”

find the code in github

Create the file ‘PostActions.js’, import this new type and firebase. This is the action we are using:

find the code in github
  • CurrentUser is the current user using the app, in our case, we.
  • .ref is where firebase has to look, I used ‘child’ with ‘posts’ but it’s the same as saying: /users/${currentUser.uid}/posts
  • ‘value’ will detect any changes in our data and will fetch it as soon an it changes
  • snapshot is our data.

If our snapshot.val() is null or undefined, will give an empty array of posts, if not, it will send our posts. And this is the reducer:

find the code in github

When called this action, it will pass to the state our payload, the empty array or the posts (remember that it will be a big object because our friend firebase).

Great! Remember to import the action in our Home component and pass it as props!

Now we are ready to make the ‘Post’ component.

As I said, we’ll pass all of this fields to props:

pic from firebase database

So, our components needs to know a lot:

  1. If we liked this picture or not (to render a red heart or a white heart)
  2. If we liked, again, to choose what we do with the image (we can like / dislike pressing the image too)
  3. Needs to know when render the “send” button, to send a comment, and this will be when the user starts typing it and the input is not empty.
  4. Needs to know if needs to render the messages or say “see messages”!

The state that this component will manage will be the ‘message’, and the ‘showMessages’ boolean to display messages or not.

We need to make the actions to tell firebase: “hey, we liked this picture” or “hey, we sent a message!”. Let’s build the actions:

First, we need to the types to our ‘types.js’ file:

find the code in github

Now, the actions, in our ‘PostActions.js’ file!

find the code in github

We’ll pass to the function, the key of the post (we passed it by props in the home component) and the number of likes the post has. If we press ‘like’, the action will set ‘liked’ as true and will add one to the total number of likes. If we press ‘dislike’, the action will set ‘liked’ as false and will subtract one from the total of likes.

Now, to store the messages is a bit different, you know, firebase doesn’t like arrays, so we’ll have an object called “comments” with the key of every comment as propery, and the keys will have the user and the comment.

We pass the post key, the number of comments and the new comment. Something we need to note, is that we are updating the values, in the like/dislike actions and the sendMessage, because when we will create a new post this values with be 0 or false (liked). But for the new comments, we will push a new object in the path /users/${currentUser.uid}/posts/${post}/comments

This again will return a big object, but with our trick there is no problem 😜.

find the code in github

Finally, our reducer!

find the code in github

Sounds pretty nice, let’s wire to redux our component:

  • As always, don’t forget to import {connect} from ‘react-redux’, {like, dislike, sendMessage} from our ‘PostActions’, and the most pretty icon you can find for our heart to like / dislike.

Our state and our actions:

find the code in github

Render method for the heart:

find the code in github

The image:

find the code in github

And our messages!

find the code in github

Our component is very very smart, he knows what to do and when to do it!

Let’s pass this in our ‘Main’ render:

find the code in github

And the wire to redux:

find the code in github

Sorry, but there are a really big big bunch of styles: (here is the direct link to the component)

find the code in github

Phew, we have now our post. This really really big post. What’s next? Oh, you guessed right, we need a way to add a post! Let’s go to our ‘AddPost.js’.

This is what our component will do:

It will simulate a “gallery” and will display the image we select. Remember that JSON file I told you to create? The JSON is this! Let’s do it!

What this components needs to do or know?

  • Display the images
  • Allow to press ‘next’ (only if a image is selected), and cancel (in our fabulous header we made)
  • Send the image we selected to the last component, ‘ConfigPost’, where will edit the title and location. (Of course we’ll send this with redux)
  • Needs to know if a image is selected and what image is selected

So, let’s make this action!

First, our type:

find the code in github

Our action:

find the code in github

Very simple right? We’ll just send the url of the picture.

And the reducer:

find the code in github

Don’t forget to import the type in the action and the reducer!

We are ready to setup our component:

  • import data from ‘./images/data.json’ (our fantastic json)
  • import { selectImage } from our PostActions
  • import Header from our common folder
  • import Actions from ‘react-native-router-flux’
  • import react and all the react-native stuff
  • We’ll use flatlist to display the miniatures

So when to render the header, and how to allow go next and back? And what about the main image? Our state will control the image, when we click one, the ‘imageSelected’ property will be true, and the image property, the url. The header only will allow to click next if ‘imageSelected’ is true.

find the code in github

What about the big image?

find the code in github

And the flatlist? We need to tell the flat list what to render (data), how to render (renderItem) and the key for each item (keyExtractor). This are the methods and our render:

find the code in github
  • renderItem will render an object (image) for each item we pass to the list (data).
  • numColumns={3}. It’s easy to guess. We want 3 columns and that’s how we get 3 columns.

Here are the export and the styles:

find the code in github

Pretty, pretty nice. We just need our last component, the interesting one. Huh.

Let’s do it quickly:

  • Action Type: “POST_ADD”
  • Action: addPost
find the code in github

We pass as parameters the img (url), location and description. Firebase will create a post with an unique key in our path (the specific path for the user). Will set the fields:

  • username: ‘Alvaro’ (hardcoded for now)
  • userpic: ‘…’ (hardcoded for now)
  • date
  • image
  • title
  • likes, comments_number: 0
  • location
  • liked: false

We will fire the action, call the reducer and we will make the app go back to the ‘Home’ component. This is our complete reducer:

find the code in github

Don’t forget to:

  • import { addPost } from actions, { Actions } from ‘react-native-router-flux’, { connect } from ‘react-redux’, and the react stuff!

Okay, our components needs to know:

  • Description
  • Location
find the code in github
  • Make a method to fire our action:
find the code in github
  • Get the image (from our reducer) and the action.

(Under our class)

find the code in github
  • Render this:
find the code in github

And as always, the styles:

find the code in github

ALRIGHT!

We have our feed and post feature ready to be tested!

I hope you enjoyed this as much as I did, if I am not as good explaining things as I believe, please tell me and I’ll try to be better! And, of course, if you have another method to do these things don’t doubt to tell me.

We’ll see again in part three, we’ll edit our profile, select our userpic, username and much other things!

Part 3: Instagram with React Native, Firebase and Redux, part 3.

Part 4: Instagram with React Native, Firebase and Redux, part 4.

Álvaro.

--

--