Create React App is a great tool for getting a React application up and running. It's a little less clear when you're building or prototyping an application that requires a server side component, like generating access tokens for Twilio Video or Chat, though. I've found it easiest to work with a server within the same project so that you can start everything up with one command.
By the end of this post you will learn how to set up an Express server that runs alongside a React app. If you can't wait then you can jump straight into the starter project on GitHub.
How it works
There is an option that you can set in Create React App's package.json
that proxies non text/html
requests through to an alternative back end. You can use this feature to proxy to applications running elsewhere, but today we want to be able to run a server within the React project itself.
We'll pull together a few npm modules that will make it possible to run one command to run our React app and an Express server at the same time so we can proxy to it.
Getting started
To follow along with the rest of this post, you will need Node.js and npm installed.
Start by creating a new React app with Create React App. Did you know, you don't have to globally install the create-react-app
package to do this? Instead, you can run:
npm init react-app MyNewApp
cd MyNewApp
Under the hood, npm init
takes an initializer name, prepends create-
to it and uses npx to install and run the command.
Run the new React application to make sure it was generated properly.
npm start
If you see a spinning React logo, then we're good to go.
Adding a server
We'll add our server dependencies to the devDependencies
of our React app as they aren't part of building the front end.
Stop the server with Cmd/Ctrl + C
and use npm
to install Express and Body Parser:
npm install express body-parser --save-dev
Add the following dependencies to help us run the front end and server together:
- node-env-run - Dominik's module for loading environment variables from a config file in development
- nodemon - for automatically restarting the server when it changes
- npm-run-all - for running multiple npm scripts at the same time
- express-pino-logger and pino-colada - for better server logging
npm install node-env-run nodemon npm-run-all express-pino-logger pino-colada --save-dev
Create a file called .env
in the project directory to store our environment variables. We don't need to add anything to it just yet, but it will be useful later for including any credentials we need for the server, like API keys.
Next, in the project directory create a new directory called server
and a server/index.js
file. We'll create a small application that we can test with. Add the following code in server/index.js
:
const express = require('express');
const bodyParser = require('body-parser');
const pino = require('express-pino-logger')();
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(pino);
app.get('/api/greeting', (req, res) => {
const name = req.query.name || 'World';
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ greeting: `Hello ${name}!` }));
});
app.listen(3001, () =>
console.log('Express server is running on localhost:3001')
);
Open package.json
and in the "scripts"
object add a new script to run the server using node-env-run
and nodemon
:
"scripts": {
// other scripts
"server": "node-env-run server --exec nodemon | pino-colada"
},
Test that the server is running correctly by running the script:
npm run server
Open http://localhost:3001/api/greeting to test. You should see a JSON response with a "Hello World!" greeting. Try adding a query parameter called name
to the URL and see what you get.
Running the server and the React app
To run both the server and React application at the same time we need to add a couple more things to package.json
.
First, we are going to set up the proxy to our server. Add the "proxy"
key to package.json
. We've already set our server to run on port 3001, so point the proxy at localhost:3001.
"proxy": "http://localhost:3001"
We need a script to run both the server and the front end at the same time. We will use npm-run-all
for this. Since we are going to be running two scripts at the same time we want to use the parallel mode. npm-run-all
gives us a handy shortcut for this with the run-p
command.
Add the following to the "scripts"
section in package.json
:
"scripts": {
// other scripts
"server": "node-env-run server --exec nodemon",
"dev": "run-p server start"
},
Run npm run dev
and both the React application and the server will start up. However, we now can't load localhost:3000/api/greeting in the browser because the Create React App proxy will just respond with the base HTML.
Let's test it from within a component in our React app instead.
Using the proxied server from React
We're going to add a form to the App
component that will use the /api/greeting
component to form a greeting and show it on the page. Add the following constructor and functions to the App component in src/App.js
:
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
greeting: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ name: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
fetch(`/api/greeting?name=${encodeURIComponent(this.state.name)}`)
.then(response => response.json())
.then(state => this.setState(state));
}
And add this form to the JSX in the render
function:
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<form onSubmit={this.handleSubmit}>
<label htmlFor="name">Enter your name: </label>
<input
id="name"
type="text"
value={this.state.name}
onChange={this.handleChange}
/>
<button type="submit">Submit</button>
</form>
<p>{this.state.greeting}</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
Open the React app in the browser, fill in your name and submit. The greeting shows that your React app is now talking to your proxied server.
This is only the start
Create React App does a great job of getting a React application started, but if you need a server side component too, it can be fiddly. In this post you've seen how to use the proxy
option and run an Express server alongside using tools like npm-run-all
.
You can check out all the code from this post in this GitHub repo and use it as a jumping off point if you want to build a React app with an Express API. As a bonus, if you want to create a Twilio Video or Twilio Chat application with React, the Twilio branch is set to return access tokens for either. Just follow the instructions in the README.
Using this template, building React applications backed by an Express server is quicker and easier. I hope it gives you a good platform for building your own ideas; I can't wait to see what you build!
Top comments (0)