How to submit form data to a RESTFUL API in React?

I am stuck and need help submitting form data in React to my express API. How can I configure the form to send a POST Request to /api/register so the user’s account can be created? (certain checks like duplicate users and such still need to be added but this is what I have so far)


Express app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var helmet = require('helmet')

var index = require('./routes/index');
var register = require('./routes/register');

var app = express();

// Connect to mongoose
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/mydatabase");

// MongoDB Users Schema (Used for Login and Registration)
var userSchema = new mongoose.Schema({
  username: String,
  email: String,
  password: String,
  salt: String,
  usergroup: 0,

});
var User = mongoose.model("User", userSchema);

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(helmet())

app.use('/', index);
app.use('/api/register', register);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

Register.js Express Route

var express = require('express');
var router = express.Router();

/* GET api/register */
router.get('/', function(req, res, next) {
  res.status(503).send("Oh noes! You sent a GET request - please send your request as a POST request. K Thx Bye!");
});

/* POST api/register */
router.post('/', function(req, res, next) {
  if (!req.body) return res.sendStatus(400)
  var regdata = new User(req.body);
  regdata.save()
  .then(item => {
     res.status(200).send("Success, Your registration has been saved to the database!")
   })
   .catch(err => {
     res.status(400).send("Unable to save the item to the database!");
   });
});

module.exports = router;

Register.js React View

import React from 'react'

var panelStyle = {
	'max-width': '80%',
	margin: '0 auto'
}

const Register = () => (
  <div>
    <div class="panel panel-primary" style={panelStyle}>
      <div class="panel panel-heading">React Forum - Register</div>
      <div class="panel panel-body">
        <form onsubmit="return false;">
          <strong>Username:</strong> <br /> <input type="text" name="username" placeholder="Nathaniel" /> <br />
          <strong>Email:</strong> <br /> <input type="email" name="email" placeholder="me@example.com" /> <br />
          <strong>Confirm Email:</strong> <br /> <input type="email" name="confirmemail" placeholder="me@example.com" /> <br />
          <strong>Password:</strong> <br /> <input type="password" name="password" placeholder="********" /> <br />
          <strong>Confirm Password:</strong> <br /> <input type="password" name="confirmpassword" placeholder="********" /> <br /><br />
          <button class="btn btn-primary">Register Account</button>
        </form>
      </div>
    </div>
  </div>
)

export default Register

Your form in your React component should post the request to the API.

You can pass something like a handlePost method to your Register.js component as a prop. Your handlePost method would likely use the native fetch API (see a sample here) or use the axios module which has slightly better cross browser support, iirc.

How familiar are you with React? Have you worked with methods / functions that you pass around before? It’s a little complicated if you’ve not done it before…

Well if you don’t want to use Redux or Redux Form, I would advise that you manage the form fields data in the component’s state. You would also need a method to post the data.

For requests like this I suggest you install “axios” from the NPM. //npm install axios --save

See below, bear in mind this is not test, I just speed typed this, you would need to review for errors. Also I only did an example for “username”.

import React, { Component } from 'react';
import axios from 'axios';

var panelStyle = {
	'max-width': '80%',
	margin: '0 auto'
}

class Register extends Component {
  constructor() {
   super();

    this.state = {
      formFields: {username: ''}
    }
  }

  render() {
    return(
     <div>
    <div class="panel panel-primary" style={panelStyle}>
      <div class="panel panel-heading">React Forum - Register</div>
      <div class="panel panel-body">
        <form onsubmit={this.formHandler(this.state.formFields)}>
          <strong>Username:</strong> <br /> <input type="text" name="username" placeholder="Nathaniel" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.username} /> <br />
          <strong>Email:</strong> <br /> <input type="email" name="email" placeholder="me@example.com" /> <br />
          <strong>Confirm Email:</strong> <br /> <input type="email" name="confirmemail" placeholder="me@example.com" /> <br />
          <strong>Password:</strong> <br /> <input type="password" name="password" placeholder="********" /> <br />
          <strong>Confirm Password:</strong> <br /> <input type="password" name="confirmpassword" placeholder="********" /> <br /><br />
          <button class="btn btn-primary">Register Account</button>
        </form>
      </div>
    </div>
  </div>

    );
  }

  inputChangeHandler(e) {
   let formFields = {...this.state.formFields};
   formFields[e.target.name] = e.target.value;
   this.setState({
    formFields
   });
  }

  formHandler(formFields) {
   axios.post('/api/register', formFields)
     .then(function(response){
       console.log(response);
       //Perform action based on response
   })
     .catch(function(error){
       console.log(error);
       //Perform action based on error
     });
  }
}

export default Register