Chris Chris - 2 months ago 20
React JSX Question

Having trouble making AJAX requests to an express server when using React Router

I'm struggling a bit with making ajax requests to pull data from a MongoDB database.

The App is written using React, using React-Router for routing and sitting on an Express server. I'm using

whatwg-fetch
to handle ajax calls.

When I try to make the ajax call, I get the following error:

parsing failed: SyntaxError: Unexpected token < in JSON at position 0


I think the problem lies with React-Router. When I navigate directly to the URL specified in the ajax call, I get the following error:

Warning: [react-router] Location "/levelsList" did not match any routes


So it looks as though React-Router is intercepting the request to the url and trying to deliver the page, which doesn't exist in the context of React-Router. So, how do I bypass React-Router for ajax calls and use the Express router instead?

Here's more of the code:

server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const path = require('path');
const httpProxy = require('http-proxy');
const mongoose = require('mongoose');
const config = require('./webpack.dev.config')

//Mongoose Schema

const Level = require('./data/models/Level');

//DB SETUP

mongoose.connect('mongodb://Localhost/Academy');

// SERVER SETUP

const app = express();
const router = express.Router();

var publicPath = path.resolve(__dirname, 'public');

compiler=webpack(config);

app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
stats: {colors: true}
}));

app.use(webpackHotMiddleware(compiler, {
log: console.log
}));

app.use(express.static(publicPath));



//Routes

app.get('*', function(req, res){
res.sendFile(path.resolve(publicPath, 'index.html'));
})

app.get('/levelsList', function(req, res){
console.log('test');
Level.find({})
.exec(function(err, levels){
if (err){
res.send('error has occurred');
} else {
console.log(levels);
res.json(levels);
}
})
})


app.listen(3000, function(){
console.log('Server running on port 3000');
});


Here's the action creator which makes the ajax call, which should then dump the info into my redux store

import 'whatwg-fetch';


export function qualDetails(){

const data = fetch('/levelsList')
.then(function(res){
return res.json()
})
.then(function(json){
console.log('parsed json: ', json)
})
.catch(function(ex){
console.log('parsing failed: ', ex) // This is where the error message is coming from
});
console.log(data);
return {
type: 'COURSE_DETAILS',
payload: data
}
}

Answer

You should try to put your app.get(*) after your route declaration.

//Routes
app.get('/levelsList', function(req, res){
    console.log('test');
    Level.find({})
        .exec(function(err, levels){
            if (err){
                res.send('error has occurred');
            } else {
                console.log(levels);
                res.json(levels);
            }
        })
})

app.get('*', function(req, res){
    res.sendFile(path.resolve(publicPath, 'index.html'));
})

app.use(express.static(publicPath));

As far as i can remmember, express will try all the paths in the exact same order. Actually /levelslist will match your get(*) and then react will try to route on /levelslist

I usualy expose my statics front app under /app and my api routes under /api prefixes. It really help to prevent any confusion

Hope it helped.