How to send an SMS from React with Twilio
Tags: sms, javascript, react, twilio
Published: 2018-10-25 00:31:51

---
title: How to send an SMS from React with Twilio
published: true
tags: sms, javascript, react, twilio
canonical_url: https://www.twilio.com/blog/send-an-sms-react-twilio
cover_image: https://s3.amazonaws.com/com.twilio.prod.twilio-docs/images/header.width-808.png
---

We talk a lot about sending [SMS messages from web applications](https://www.twilio.com/docs/sms/send-messages), but what about sending SMS messages from a React application? There's a bit more to it than just [the server-side version](https://www.twilio.com/blog/2016/04/send-text-in-javascript-node-in-30-seconds.html), but it won't take us long.

### Why shouldn't I use the REST API from the client-side?

Technically you could send an SMS using the Twilio REST API directly from a JavaScript client-side application. But (and it's a very big "but") if you were to do that, you would expose your Twilio credentials to anyone using your site. A malicious user could then take those credentials and abuse them, running up a huge bill with your account.

![An animation showing a fake hacker, with a balaclava and extra hands.](https://s3.amazonaws.com/com.twilio.prod.twilio-docs/images/WU8JMLBGyKsTCY1u_Qa7mPji5mpT1SqxmgsO3eCJSN77kn.width-800.gif)

_Live view of a hacker with your account credentials_

To avoid this we will create a back end application that implements the Twilio REST API, wraps up your credentials and sends SMS messages for you. Then you can call your back end from your React application and send SMS messages without distributing your credentials to the internet.

### Our tools

For our application to send text messages using the Twilio REST API we will need the following:

- A Twilio account and phone number that can send SMS messages (you can [sign up for a Twilio account for free here](https://www.twilio.com/try-twilio))
- [Node.js](https://nodejs.org/en/download/) to build our React app and to run our server (you can build the server-side component of this in any language, but in this post we're going to do so in Node so we can keep it all JavaScript)
- [React Dev Tools](https://github.com/facebook/react-devtools) for your browser (optional, but really useful for seeing what goes on in the application

To get started, download or clone the [react-express-starter application](https://github.com/philnash/react-express-starter) that I built in [my last blog post](https://dev.to/twilio/set-up-a-react-app-with-a-nodejs-server-proxy-2pgc).

```bash
git clone https://github.com/philnash/react-express-starter.git
```

Change into the directory and install the dependencies.

```bash
cd react-express-starternpm install
```

In the project directory, create a file called `.env`:

```bash
touch .env
```

You can now test the project is working by running `npm run dev`. The application will load in your browser at localhost:3000.

This starter application is set up to have both a React application and an [Express](http://expressjs.com/) application in the same project that you can run concurrently. If you want to find out how this works, check out [this blog post](https://dev.to/twilio/set-up-a-react-app-with-a-nodejs-server-proxy-2pgc).

### Building the server-side

As discussed, we need to make the Twilio API calls from the server. We'll add an endpoint to the Express server that can be called from our React application. Start by installing the [Twilio Node.js module](https://www.npmjs.com/package/twilio). Note: for the purposes of this application I'm saving the server dependencies as development dependencies to separate them from the client-side dependencies.

```bash
npm install twilio --save-dev
```

Next, we need to configure the application with our Twilio credentials. Gather your Twilio Account Sid and Auth Token from the [Twilio console](https://www.twilio.com/console) along with a [Twilio phone number](https://www.twilio.com/console/phone-numbers/incoming) that can send SMS messages. Enter all three into the `.env` file you created earlier like so:

```bash
TWILIO_ACCOUNT_SID=YOUR_ACCOUNT_SID
TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKEN
TWILIO_PHONE_NUMBER=YOUR_TWILIO_PHONE_NUMBER
```

This will [set your credentials in the environment](https://www.twilio.com/blog/2017/08/working-with-environment-variables-in-node-js.html). Now, open `server/index.js` so that we can get started with the code necessary for sending the message. Under the other module requires at the top of the file, require and initialise the Twilio library with the credentials from the environment.

```javascript
const express = require('express');
const bodyParser = require('body-parser');
const pino = require('express-pino-logger')();
const client = require('twilio')(
  process.env.TWILIO_ACCOUNT_SID,
  process.env.TWILIO_AUTH_TOKEN
);
```

We'll be sending the data to the endpoint we're building as JSON, so we'll need to be able to parse the JSON body. Configure the Express app with body parser's JSON parser:

```javascript
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());app.use(pino);
```

Make a route for a `POST` request. Add the following below the route for `/api/greeting`:

```javascript
app.post('/api/messages', (req, res) => {

});
```

We're going to respond with JSON too, so set the `Content-Type` header to `application/json`.

```javascript
app.post('/api/messages', (req, res) => {
  res.header('Content-Type', 'application/json');

});
```

We'll then [use the Twilio client we initialised earlier to create a message](https://www.twilio.com/docs/sms/send-messages?code-sample=code-send-an-sms-message&code-language=Node.js&code-sdk-version=3.x). We'll use our Twilio number as the `from` number and get the `to` number and `body` of the message from the incoming request body. This returns a [Promise](https://www.twilio.com/blog/2016/10/guide-to-javascript-promises.html) that will fulfill when the API request succeeds or reject if it fails. In either event we will return a JSON response to tell the client-side whether the request was a success or not.

```javascript
app.post('/api/messages', (req, res) => {
  res.header('Content-Type', 'application/json');
  client.messages
    .create({
      from: process.env.TWILIO_PHONE_NUMBER,
      to: req.body.to,
      body: req.body.body
    })
    .then(() => {
      res.send(JSON.stringify({ success: true }));
    })
    .catch(err => {
      console.log(err);
      res.send(JSON.stringify({ success: false }));
    });
});
```

That's all we need on the server, let's get started on the React portion.

### Building the client-side

On the client-side, we can encapsulate the form to send our SMS via the server entirely in just one component. So, in the `src` directory create a new component called `SMSForm.js` and start with the boilerplate for a component:

```javascript
import React, { Component } from 'react';

class SMSForm extends Component {

}

export default SMSForm;
```

We're going to create a form that a user can fill in with a phone number and message. When the form is submitted it will send the details to our server endpoint and send the message as an SMS to the number.

Let's build the `render` method for this component first: it will include a form, an input for the phone number, a textarea for the message and a button to submit:

```jsx
  render() {
    return (
      <form>
        <div>
          <label htmlFor="to">To:</label>
          <input
             type="tel"
             name="to"
             id="to"
          />
        </div>
        <div>
          <label htmlFor="body">Body:</label>
          <textarea name="body" id="body"/>
        </div>
        <button type="submit">
          Send message
        </button>
      </form>
    );
  }
```

We can add some CSS to style this form a bit. Create the file `src/SMSForm.css` and add the following:

```css
.sms-form {
  text-align: left;
  padding: 1em;
}
.sms-form label {
  display: block;
}
.sms-form input,
.sms-form textarea {
  font-size: 1em;
  width: 100%;
  box-sizing: border-box;
}
.sms-form div {
  margin-bottom: 0.5em;
}
.sms-form button {
  font-size: 1em;
  width: 100%;
}
.sms-form.error {
  outline: 2px solid #f00;
}
```

Import the CSS at the top of the SMSForm component:

```javascript    
import React, { Component } from 'react';
import './SMSForm.css';
```

Now, import the component into `src/App.js` and replace the render method with the following:

```jsx
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import SMSForm from './SMSForm';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />

          <SMSForm />
        </header>
      </div>
    );
  }
}

export default App;
```

Start your application with `npm run dev` and you'll see the form on the page.

 

![](https://s3.amazonaws.com/com.twilio.prod.twilio-docs/images/lQ_7J7OP9Wc8uM5lAWxNkavJ2bGd8F_i0ONhZvdHXFysVt.width-500.png)

The form doesn't do anything yet, so let's fix that.

### Making an interactive form in React

To hook the HTML form up with the component we need to do a few things:

- Keep the state of the input and textarea up to date in the state of the component
- Handle submitting the form and sending the data to the server
- Handle the response from the server and clear the form if the message was sent successfully, or show an error if it wasn't

We'll start by setting up some initial state in the constructor. We'll need to store the form inputs, whether the form is currently being submitted (so that we can disable the submit button) and whether there was an error. Create the constructor for the component as follows:

```javascript
class SMSForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      message: {
        to: '',
        body: ''
      },
      submitting: false,
      error: false
    };
  }

  // rest of the component
}
```

We'll need a method that can handle changes in the form fields and update the state. We could create two methods, one for the input and one for the textarea, but since the names of the form elements and items in the state match up we can build one method to cover both.

```javascript
  onHandleChange(event) {
    const name = event.target.getAttribute('name');
    this.setState({
      message: { ...this.state.message, [name]: event.target.value }
    });
  }
```

Note here that we use [ES2015's computed property names](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names) to set the right property in the state and the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to fill in the rest of the state.

We'll need to bind this method to the object to ensure that `this` is correct when we use it to receive an event. Add the following to the bottom of the constructor:

```javascript
  constructor(props) {
    super(props);
    this.state = {
      message: {
        to: '',
        body: ''
      },
      submitting: false,
      error: false
    };
    this.onHandleChange = this.onHandleChange.bind(this);
  }
```

We can now update our rendered JSX to set the value of the form fields using the current state and handle updates with our `onHandleChange` method:

```jsx
  render() {
    return (
      <form>
        <div>
          <label htmlFor="to">To:</label>
          <input
            type="tel"
            name="to"
            id="to"
            value={this.state.message.to}
            onChange={this.onHandleChange}
          />
        </div>
        <div>
          <label htmlFor="body">Body:</label>
          <textarea
            name="body"
            id="body"
            value={this.state.message.body}
            onChange={this.onHandleChange}
          />
        </div>
        <button type="submit">Send message</button>
      </form>
    );
  }
```

Reload the app and you'll be able to update the form fields. If you have the [React dev tools](https://github.com/facebook/react-devtools) for your browser, you'll be able to see the state updating too.

 

![](https://s3.amazonaws.com/com.twilio.prod.twilio-docs/images/_dzcSo7MrETpFCBo-yhmOkD376ckMEWm3HHhEY8YF4CLbY.width-500.png)

Now we need to handle the form submission. Build another function, `onSubmit`,  that starts by updating the `submitting` state property to true. Then use the [`fetch` API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)  to make the request to the server. If the response is successful then clear the form and set `submitting` to false. If the response is not a success, set `submitting` to false but set `error` to true.

```javascript
  onSubmit(event) {
    event.preventDefault();
    this.setState({ submitting: true });
    fetch('/api/messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(this.state.message)
    })
      .then(res => res.json())
      .then(data => {
        if (data.success) {
          this.setState({
            error: false,
            submitting: false,
            message: {
              to: '',
              body: ''
            }
          });
        } else {
          this.setState({
            error: true,
            submitting: false
          });
        }
      });
  }
```

Like with the `onHandleChange` method, we also bind this method in the constructor:

```javascript
  constructor(props) {
    super(props);
    this.state = {
      message: {
        to: '',
        body: ''
      },
      submitting: false,
      error: false
    };
    this.onHandleChange = this.onHandleChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);
  }
```

Now, in the JSX we add the `onSubmit` method as the submit handler on the form. We also set the form's class to "error" if we receive an error from the request. And while the form is submitting we set the button's `disabled` property.

```jsx
  render() {
    return (
      <form
        onSubmit={this.onSubmit}
        className={this.state.error ? 'error sms-form' : 'sms-form'}
      >
        <div>
          <label htmlFor="to">To:</label>
          <input
            type="tel"
            name="to"
            id="to"
            value={this.state.message.to}
            onChange={this.onHandleChange}
          />
        </div>
        <div>
          <label htmlFor="body">Body:</label>
          <textarea
            name="body"
            id="body"
            value={this.state.message.body}
            onChange={this.onHandleChange}
          />
        </div>
        <button type="submit" disabled={this.state.submitting}>
          Send message
        </button>
       </form>
    );
  }
```

This is all we need, so refresh the app again and enter your mobile number and a message to send. Submit the form and if the details are correct then your message will be sent, if not, the form will show that the state is in error.

![Now when entering incorrect values the form shows an error and when you enter the correct values the message is sent.](https://s3.amazonaws.com/com.twilio.prod.twilio-docs/images/success.width-500.gif)

### Sending messages and keeping your credentials safe

Sending SMS messages from a web app is cool. Sending SMS messages from your React app without exposing your credentials is even cooler 😎.

You can check out all the code from this example application in the [GitHub repo](https://github.com/philnash/send-sms-react-twilio).

Now that you have the basis of a React app that can send SMS messages you could make some improvements. First would likely be better validation and error messages. With a similar design you could add [phone number lookups](https://www.twilio.com/docs/lookup/api), [generate phone calls](https://www.twilio.com/docs/voice/api/call) or [implement two factor authentication](https://www.twilio.com/docs/authy/api/one-time-passwords) right from your React app too.

I’d love to hear about the app you’re building with React. Drop me a comment below, hit me up on Twitter at [@philnash](https://twitter.com/philnash) or send an email my way at [philnash@twilio.com](mailto:philnash@twilio.com).