Handling Dev vs Production API Calls using create-react-app

This post documents a brute-force approach I took to alternating between development and production databases in the PLURview app.

I built a simple apiAdapter.js file in my src/ directory, which sets an API_URL variable for my fetch() calls. PLURview is based on create-react-app, which has the ability to distinguish between dev and production through process.env variables.

The Problem

There were about 10 different calls to PLURview’s internal API spread throughout the front-end codebase. The API URLs were hard-coded, which required a project-wide search-and-replace for every commit (local vs production).

The other problem was complexity of information when it came to researching how to accomplish this. The app is hosted on Heroku and it automatically updates from Github.

I looked into using Heroku’s environment variables, which I had found useful in the past for storing API keys. All of my calls to external APIs go through the back-end, which is a private repo.

Ultimately a proper DevOps style solution appeared to be too heavy a solution for the amount of time I had to research and implement a solution.

The Solution

First, I modified my NPM scripts to set the dev environment variable:

"scripts": {
    "start": "REACT_APP_STAGE=dev react-scripts start",
    ...
  }

When you set a variable starting with REACT_APP you’ll have access to it in your app along the pattern of process.env.REACT_APP_STAGE.

Next, in apiAdapter.js I created a simple ternary based on the environment variable:

let API_URL

process.env.REACT_APP_STAGE === 'dev'
  ? API_URL = 'http://localhost:3001/api/v1'
  : API_URL = 'https://plurview-api.herokuapp.com/api/v1'

Finally, I collected all those fetch calls into apiAdapter.js so I could interpolate the API_URL based on the environment:

export const fetchArtists = () => {
  return fetch(`${API_URL}/artists`)
}

The adapter works the same way in the app as Redux actions. A component can import and use only the calls it needs:

import {fetchColorGuide} from '../../apiAdapter'

...

toggleDetails = () => {
    fetchColorGuide()
    .then(res => res.json())

Conclusion

This was a good intermediate step between ad hoc fetch() calls and something more elegant. In the process I found I probably had more API calls going on than necessary, and some of my naming conventions could use better semantics.

The process of abstracting these calls also shined some light on components and endpoints I was no longer using, which helped me pare down the codebase a bit overall.

1 thought on “Handling Dev vs Production API Calls using create-react-app

  1. Nice approach. However, unless you have unique stages, rather than using process.env.REACT_APP_* to set the stage, you can simply use process.env.NODE_ENV that will give the strings ‘development’ (with npm start), ‘test’ (with npm test), and ‘production’ (after npm build).

    from the ‘create-react-app’ documentation here: https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables

    Thank you for writing this up though, it was your blog post that led me to search for more on the REACT_APP_* vars. Very helpful.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Mark Bello

Mark Bello