Julian
Julian

Reputation: 657

React JS and Express POST route not found 404

My problem is I am trying to add an edit function to my project. I have added in a /edit router to my classroom.js file and I go to edit the flag through the app and I get POST /classroom/edit 404 398.484 ms - 1355 in my console log. In the browsers console log I get:

App.js:32 POST http://localhost:3002/classroom/edit 404 (Not Found)
App.js:52 Error: Bad response from server
    at App.js:40

React: App.js

import React, { Component } from 'react';
import './App.css';

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      toggle: false,
      toggleIdx: 0,
      classroom: [],
      flagreason: '',
      msg: ''
    };
    this.eventHandler = this.eventHandler.bind(this);
    this.logChange = this.logChange.bind(this);
    this.handleEdit = this.handleEdit.bind(this);
  }

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

  handleEdit(event) {
    event.preventDefault()
    var data = {
      flagreason: this.state.flagreason,
      id: this.state.toggleIdx
    }
    fetch("/classroom/edit", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    }).then(function(response) {
      if (response.status >= 400) {
        throw new Error("Bad response from server");
      }
      return response.json();
    }).then(function(data) {
      console.log(data)
      if (data === "success") {
        this.setState({
          msg: "Flag Reason has been edited."
        });
        console.log('Successful Update!');
      }
    }).catch(function(err) {
      console.log(err)
    });
  }

  eventHandler(event, idx) {
    this.setState((prevState) => ({
        toggle: !prevState.toggle,
        toggleIdx: idx
      })
    );
  }

  componentDidMount() {
    fetch("/classroom")
    .then(res => res.json())
    .then(classroom => this.setState({ classroom }))
  }

  render() {
    return (
      <div className="App">
                <div className="wrapper">
                    <h1>Classroom</h1>
                    {this.state.classroom.map((classroom, idx) =>
                        <div className="child" key={classroom.id}>
              <p className="detail">Child's Name: <span className={classroom.childflagged}>{classroom.childsname}</span> <i title={classroom.flagreason} className={'fa fa-flag flag' + classroom.childflagged}></i><i title={classroom.starreason} className={'fa fa-star star' + classroom.starstudent}></i></p>
              <p className="detail">Parent's Phone Number: {classroom.parentsnumber}</p>
              <div className="actionMenu">
                <button className="flags" id={classroom.id} onClick={e => this.eventHandler(e, idx)}>Edit Flags</button>
                <button className="results">View Results</button>
                <button className="profile">View Profile</button>
              </div>
              <div className="actionForm">
                <div>
                  <form id={"flagform" + classroom.id} className={(this.state.toggle && (this.state.toggleIdx === idx)) ? '' : 'hide'} onSubmit={this.handleEdit} method="post" autoComplete="no">
                    <input type="hidden" name="id" value={classroom.id} />
                    <input type="text" onChange={this.logChange} value={this.state.flagreason} name="flagreason" placeholder="Reason For Flag" />
                    <input type="submit" name="submit" value="Save Changes" />
                  </form>
                </div>
              </div>
            </div>
          )}
                </div>
      </div>
    );
  }
}

export default App;

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 index = require('./routes/index');
var classroom = require('./routes/classroom');

var app = express();

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

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
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('/', index);
app.use('/classroom', classroom);

// 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');
});

app.listen(3001);

module.exports = app;

classroom.js

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

var pool = mysql.createPool({
  connectionLimit : 30,
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'dbname'
});

/* GET Classroom listing. */
router.get('/', function(req, res, next) {

    console.log('A Client Requested Data...');

  pool.query('SELECT * FROM classroom ORDER BY childsname ASC', function(err, results) {
    if (err) throw err
    var array = [];
    for(var i = 0, len = results.length; i < len; i++) {
      array.push(results[i]);
    }

        res.json(array);
    });

});

/* EDIT Child Flag */

router.get('/edit', function(req, res, next) {

  console.log('A flag was edited...');

  pool.query("UPDATE classroom SET flagreason = '"+req.body.flagreason+"' WHERE id = '"+req.body.id+"'", function (err, results, fields) {
      if(err) throw err;
      res.send(JSON.stringify(results));
  });
});

module.exports = router;

Can anyone help me, show what I need to change and then explain why it's not working so I can learn from the mistake?

Upvotes: 2

Views: 14664

Answers (2)

Gleb Kostyunin
Gleb Kostyunin

Reputation: 3863

You'll need to update the part of your classroom.js file on the server to use post method:

router.post('/edit', function(req, res, next) {

  console.log('A flag was edited...');

  pool.query("UPDATE classroom SET flagreason = '"+req.body.flagreason+"' WHERE id = '"+req.body.id+"'", function (err, results, fields) {
      if(err) throw err;
      res.send(JSON.stringify(results));
  });
});

Currently it is expecting a GET request and you are sending a POST, so it does not know how to handle it. The rest should be fine.

Upvotes: 4

Chaim Friedman
Chaim Friedman

Reputation: 6253

Based on the code provided it would appear that there are 2 issue causing the 404. The first one is that in your react code you are making a post request, but the route it a get.

The second issue, is that in your react code you are attempting to reach /classroom/edit, but based on the code provided it should only be /edit.

UPDATE

With the additional code provided, the issue seems to be from the fact that you are attempting to make post to a get route.

The route in the react code should in fact be /classroom/edit and the route handler should be changed to a post.

Upvotes: 2

Related Questions