Basic React Redux App

React/Redux Node/Express App

Basic React Redux App

by John Vincent

Posted on October 15, 2017

Build the hot cold application using React/Redux and Node/Express

Final Result

My Git repository

Git Readme

Heroku git

App at Heroku


Local: /Users/jv/Desktop/MyDevelopment/github/thinkful/hot-cold

Client App

cd client

Start the DevServer

npm start


Make a production build

npm run build

makes app files in client/dist

The port is set in webpack.config.js

	devServer: {
		contentBase: path.join(__dirname, 'dist'),
		compress: true,
		// inline: true,
		port: 8025,
		proxy: {
			'/api/**': { target: 'http://localhost:3001', changeOrigin: true, secure: false },

Notice the build directory

contentBase: path.join(__dirname, 'dist'),

Files are created there with with this code in webpack.config.js

	output: {
		path: path.resolve('dist'),
		filename: 'bundle.js',


Client app is making asynchronous calls to the node/express application.

For example, client/src/actions/fetchTopScore.actions.js

export const fetchScore = () => (dispatch) => {
	const url = '/api/score/get';
	return fetch(url)
		.then((response) => {
			if (!response.ok) {
				const error = new Error(response.statusText);
				error.response = response;
				throw error;
			return response;
		.then(response => response.json())
		.then(data => dispatch(fetchScoreSuccess(data.score)))
		.catch(error => dispatch(fetchScoreError(error)));

Notice the URL

const url = '/api/score/get';

which will make a call to the react devServer which is running on port 8025, which will proxy the request to the node/express app running on port 3001


port: 8025,
proxy: {
	'/api/**': { target: 'http://localhost:3001', changeOrigin: true, secure: false },

Thus, all requests to http://host:8025/api/* are proxied to /http://localhost:3001/api/*

Server App

cd server
npm start

listening on port 3001


# LOG_ENV=dev
# LOG_ENV=heroku
# LOG_ENV=prod


exports.PORT = process.env.PORT || 3001;

Intentionally not using 3000 in case anything in the client defaults to 3000.



app.use((req, res, next) => {
	res.header('Access-Control-Allow-Origin', '*');
	res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
	res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
	if (req.method === 'OPTIONS') {
		logger.debug('Request method = "OPTIONS"');
	} else {

Please see Cross-Origin Resource Sharing

Notice that method = "OPTIONS" is handled.

app.use(express.static(path.resolve(__dirname, '../../client/dist/')));

This allows the production built React application to be accessible as /

Test Using Mocha

npm test

Note that for Mocha "mocha": "^4.0.1", it is now necessary to add --exit, for example:

"test": "LOG_LEVEL=info mocha ./test --exit",


To build the app at Heroku it is necessary to provide package.json in the root of the project.


  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "cd server && node server.js",
	"test": "cd server && npm install && LOG_LEVEL=info mocha ./test --exit",
	"heroku-postbuild": "cd server && npm install && cd ../client && npm install --only=dev && npm install && npm run prod"
  "keywords": [],
  "author": "",
  "license": "ISC"

Notice that Heroku requires these scripts to be able to install, test and run the application.

Travis CI

For details, see Travis Continuous Integration


curl -H "Content-Type:application/json" "http://localhost:3001/api/score/get" 

curl -H "Content-Type:application/json" "http://localhost:8025/api/score/get" 


curl -i -X POST -H "Content-Type:application/json" http://localhost:3001/api/score/send -d '{"score": 51}'