Abel Hristodor
Abel Hristodor

Reputation: 77

Can't post data to Express using React

This is my first time trying to make a full stack app. I already have experience with Django but now i wanted to try using Express.js So, i made this simple route in express:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var logger = require('morgan');

var User = require('../User/User');


app.use(logger("short"));

app.post("/addUser", (req, res) => {
User.create({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password
}, (err, user) => {
    if (err) return res.status(500).json({auth: false})
    res.status(200).json(
        {
            email,
            name
        }
        );
    });
});

this is the User schema:

const mongoose = require("mongoose")
const Schema = mongoose.Schema;

const UserSchema = new Schema(
    {
        name: String,
        email: String,
        password: String,
    },
    {timestamps: true}
);
mongoose.model("User", UserSchema);

module.exports = mongoose.model("User");

I already tried doing some post requests using insomnia. They all worked But when i make a post request using react it creates an object but its name, email, password fields are empty, like this:

createdAt: "2018-11-22T16:59:51.844Z"
updatedAt: "2018-11-22T16:59:51.844Z"
__v: 0
_id: "5bf6e0878bd6663807e57dec"

this is my react code - it's in a func that's called when the form is submitted - (I already added the express server as a proxy):

    axios.post('/api/auth/addUser', {
        name:  register_name,
        email: register_email,
        password: register_password
    })
    .then(res => res.json())
    .catch(err => console.log(err))

I get code 200 on express' console but the obj doesn't have any data. Can you help me? - I'm still a beginner to React and Express

Edit: React Component

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

export default class Register extends Component {
    constructor(props) {
        super(props)
       this.state = {
        register_name: "",
        register_email: "",
        register_password: ""
    }

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);

    }

    handleChange(event) {
        this.setState({[event.target.name]: event.target.value})
    }

    handleSubmit(event) {
    event.preventDefault();
    const { register_name, register_email, register_password } = this.state
    axios.post('/api/auth/addUser', {
        name:  register_name,
        email: register_email,
        password: register_password
    })
    .then(res => res.json())
    .catch(err => console.log(err))

    console.log(this.state)

    this.clearInputs();

}

    render() {
        return (
        <div>
            <form method={"POST"} onSubmit={this.handleSubmit} id={"register-form"}>
                <label htmlFor={"register_name"}></label>
                <input type={"text"} name={"register_name"} id={"register_name"} placeholder={"name"} value={this.state.register_name} onChange={this.handleChange}></input>
                <label htmlFor={"register_email"}>Email</label>
                <input type={"email"} name={"register_email"} id={"register_email"} placeholder={"email"} value={this.state.register_email} onChange={this.handleChange}></input>
                <label htmlFor={"register_password"} >Password</label>
                <input type={"password"} name={"register_password"} id={"register_password"} placeholder={"password"} value={this.state.register_password} onChange={this.handleChange}></input>
                <button type={"submit"}>Submit</button>
            </form>
        </div>
    )
}

}

Upvotes: 0

Views: 2341

Answers (3)

bFunc
bFunc

Reputation: 1465

Everything works out of the box with just bare fetch. Here is gist, just make sure you attached bodyParser to express instance

const bodyParser = require('body-parser');
...
app.use(bodyParser.json());

axios lib is useful if you want to upload physical files with FormData

Upvotes: 0

Rich Churcher
Rich Churcher

Reputation: 7664

There's a series of potential problems here. First, there's no particular need to make a urlencoded form submission here: just use JSON. Your submit could then look something like:

handleSubmit (e) {
  e.preventDefault()
  const { email, name, password } = this.state
  axios.post('/api/auth/adduser', {
      email,
      name,
      password
    })
    .then(res => /* ... */)
    .catch(err => /* ... */)
}

On the server, you're probably after res.json rather than res.send.

const { email, name, password } = req.body
// ...
res.status(201).json({
  email,
  name
})

Also note that you don't need bodyParser these days (you can just use express.json()).

Finally, you should use event.target.name in your handleChange as the names match the names of your values in component state:

handleChange (e) {
  this.setState({ [e.target.name]: event.target.value })
}

Simple example

Client:

const CLEAR_STATE = {
  email: '',
  name: '',
  password: '',
  message: ''
}

export default class App extends Component {
  state = CLEAR_STATE

  handleChange = e => this.setState({
    [ e.target.name ]: e.target.value
  })

  handleSubmit = e => {
    e.preventDefault()
    const { email, name, password } = this.state
    axios.post('/', { email, name, password })
      .then(({ data }) => this.setState({
        ...CLEAR_STATE,
        message: `You sent: ${data.email}, ${data.name}, ${data.password}.`
      }))
      .catch(({ message }) => this.setState({ message }))
  }

  render () {
    return (
      <>
        <form onSubmit={this.handleSubmit}>
          <input
            type='text'
            name='email'
            value={this.state.email}
            onChange={this.handleChange} />
          <input
            type='text'
            name='name'
            value={this.state.name}
            onChange={this.handleChange} />
          <input
            type='password'
            name='password'
            value={this.state.password}
            onChange={this.handleChange} />
          <input type='submit' value='Register' />
        </form>
        {this.state.message && <p>{this.state.message}</p>}
      </>
    )
  }
}

Server:

app.use(express.json())

app.post('/', (req, res) => {
  const { name, email, password } = req.body
  res.status(201).json({ name, email, password })
})

Upvotes: 0

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196236

You are using the [event.target.id] of the changed input element to update the state.

You state expects name,email,password but receives register_name,register_email,register_password.

You should change the id of the input elements to match those in the state or you should use the name attribute since that is what matches .

this.setState({[event.target.name]: event.target.value});

Keep in mind that the attribute htmlFor of the label elements also needs to match the id and not the name of the element it is linked to.


Also, you should have noticed that something was wrong since your code will not update the input elements while you type.

Upvotes: 1

Related Questions