Tutorial: Tomodachi — Contacts Management connecting Heroku, NodeJS, Postgres & React JS/Native

Sunim Acharya
Aug 3 · 7 min read
React JS implementation on Heroku
Download for Play Store

Realized I haven’t published an open-source tutorial in a long, so preparing a well documented tutorial. Will try to keep short and insightful for everyone. Maybe a Youtube series soon.

For test: Heroku App and Play Store

Github: Tomodachi is where the codebase is and this tutorial will work in tandem with the repo rather than full-blow step wise guide.

Tomodachi is a dummy application built using Node, React and Postgres with addition of React-Native to the system. The end-goal is to allow user to enter Contacts of their friend circle after Logging in with Facebook with basic features to edit and delete them.


Let’s start with the Backend:

package.json for Node Server

Notice I am using concurrently to run the React app and Server at the same time. The –kill-others-on-fail flag will kill other processes if one exits with a non zero status code.

Install nodemon globally and the server dependencies:

npm i nodemon -g
yarn

Install heroku if you plan to use it:

npm install -g heroku-cliheroku create <app_name>

Currently, we have two applications. If we don’t set up CORS, our React application will not be able to communicate with the backend. We will use the Node.js library cors in app.js and by setting origin to true, we have allowed any origin to access the resource. methods is used to control Access-Control-Allow-Methods CORS header. With the property credentials we are controlling the Access-Control-Allow-Credentials CORS header. The last exposedHeadersis used to indicate which headers can be exposed as part of the response.

CORS Options

I am using Passport package for the OAuth authentication over /api/auth/facebook. It requires configuration of some parameters which you can get from https://developers.facebook.com

Facebook Dev Console

Now the clientID and clientSecret is set in Repo through .env variables as process.env.facebook_api_key and process.env.facebook_api_secret by setting them as:

heroku config:set facebook_api_key=api-keyheroku config:set facebook_api_secret=api-secret

But, for convenience, you can set them in configuration/config.js and use them as:

clientID: config.facebook_api_key,clientSecret: config.facebook_api_secret

Once we Token from the frontend, we use passport-facebook-tokento get the access Token. Notice that localhost:3000 is the ReactJS client. Next, for new user, we insert the id and Name to users database on Postgres.

As we are using Postgres, we need to setup two table over a database, users and contacts, and as we will be deploying to Heroku, need need to setup Postgres over Heroku and use it’s connection String with SSL set to true for Postgres client.

heroku addons:create heroku-postgresql:hobby-dev

To Push your Local DB:

heroku pg:push <database_name> DATABASE_URL

As we will be applying the connectionString through environment variable as connectionString = process.env.DATABASE_URL

PostgreSQL 11 on Mac OS

Next, when passing the payload back to client, we pass a JWT token based on user id and “my-secret” as the key expiring at 60x120.

jwt.sign({id: auth.id},"my-secret",{expiresIn: 60 * 120});

Now, we callback /api/contacts/get/:id endpoint to get the contact list based on user id. But it requires passing Bearer Token which we have already sent to the client when logging in for verification.

jwt.verify(token, "my-secret", {expiresIn: 60 * 120})

If the token is valid, we select the contacts based on the user id from contacts table and send it back.

Now, other major endpoints are: /api/contacts/add ,/api/contacts/delete/:id , /api/contacts/update/:id to add, delete and edit the contacts table based on the user id after JWT token verification. The endpoints are SQL injection protected by using placeholder scheme but needs further protection.


Now, to serve the Backend and database, the scheme is deployed to Heroku, thus requires the configuration as:

const port = process.env.PORT || 5000;
if (process.env.NODE_ENV === "production") { app.use(express.static(path.join(__dirname, "client/build"))); app.get("*", function(req, res) { res.sendFile(path.join(__dirname, "client/build", "index.html"));});}app.listen(port, () => console.log(`Listening on port ${port}`));

Also, Make sure you Update the CallBack URL over the Facebook Dev Console in Products/Facebook Login/Settings with new Heroku Url Callback. Also, make sure to addApp Domain and Website Site URL inSettings/Facebook Login/Settings


Now for the React Frontend:

package.json for React.js

Head over to client folder. The key to using an Express back-end server with a project created with create-react-app is to use a proxy. This tells the Web-pack development server to proxy our API requests to our API server, given that our Express server is running on localhost:5000in dev mode. Make sue to have HTTPS=true in .env file for local development.

We will majorly be using Hooks and useState instead of LifeCycle components and styled-components for CSS-in-JS.

What is a Hook? A Hook is a special function that lets you “hook into” React features.

What does calling useState do? It declares a “state variable”. Our variable is called countbut we could call it anything else, like banana. This is a way to “preserve” some values between the function calls — useState is a new way to use the exact same capabilities that this.state provides in a class.


In src/App.jsif the isAuthenticated state variable is false, Login Button is shown and onClicking it, react-facebook-login is called to send the callback response accessToken to Express Backend using axioswhich will receive the x-auth-token header and user Data. Then the received id is sent back to hit the api to get the contactsList along with the bearer token just received. If response is sent back, isAuthenticated is set to true rendering the ContactList.

The avatar and user Name is rendered on Top right corner with Contact List at the center along with react-floating-action-button on bottom right corner, which onClick shows rodal for Modal to Add Contact.

If valid values are sent by onClick Send button over Add Contact Modal, endpoint is hit with the JWT token and payload and if response is sent back, the modal is closed with the Contact List populated. OnClicking a list key, ContactInfo component is shown with details and buttons to edit and delete.

On clicking delete, endpoint is called with again JWT token and id to delete the particular value.Also, on clicking edit, Edit modal is shown following same process as Add Contact Modal, but only updating the parameters.If the process is successful, the current Contact Info is popped off the render view in both cases.


Finally, for the React-Native Frontend:

package.json for React-Native-App

Head over to react-native-app folder. The directory is independent to the others, cause well it is for Mobile app, what do you expect?

In future, might add Auto-Login cause we have already passed the token, just AsyncStorage might do the work.

As FbLogin is the root view, we initially navigate to it, which renders the Login Button and onPressing it, react-native-fbsdk is called to get the accessToken and we send it to Express Backend using axioswhich will receive the x-auth-token header and user Data. Then the received id is sent back to hit the api to get the contactsList along with the bearer token just received. If response is sent back, we render ListView by calling Action and passing it the props.

Key Hashes for the Android App

Make sure to add the KeyHash for Debug apk or Release apk if you plan to build. May use KeyHash from the PlayStore.

Basic Usage of Android App
Basic Usage of Android App
Android App

The ListView shows FlatList over ScrollView and avatar rendered on Top right corner along with react-native-floating-action on bottom right corner, which onPress navigates to AddnEdit screen with token and userDetails with setting edit variable to false to make it behave as Add Contact Screen.

The ListView shows FlatList over ScrollView and avatar rendered on Top right corner along with react-native-floating-action on bottom right corner, which onPress navigates to AddnEdit screen with token and userDetails with setting edit variable to false to make it behave as Add Contact Screen.

If valid values are sent by onClick Send button over Add Contact Screen, endpoint is hit with the JWT token and payload and if response is sent back, AddnEdit screen is popped back with the Contact List populated. OnPressing a list key on FlatList , react-native-modal is shown for ContactInfo component is shown with details linking to their placeholders and buttons to edit and delete.


That should help you get started with the repo along with the basic architecture. It does need further implementation of better codebase, security measures and pattern. Do create pull requests and issues.🙏

Any questions? Go ahead and ping me at:

sunim.com.np

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade