Home > Software design >  Why Doesn't the Fetch API Call My API Endpoint I Created in Express?
Why Doesn't the Fetch API Call My API Endpoint I Created in Express?

Time:07-30

I am wondering why the Fetch API in javascript isn't call the endpoint I created in express. When I start my server and go to the '/characters' endpoint, it returns correctly formatted JSON.

Here is my express index.js

const app = express();
const PORT = 3000;

const charactersRoute = require('./routes/characters');

//Characters Route
app.use('/characters', charactersRoute)

app.listen(PORT, function(err) {
    if(err) console.log(err);
    console.log(`Server is listening on port ${PORT}`)
})

Here is my Characters Route

const express = require('express'); // Web Framework
const https = require('https');
const router = express.Router();
const PORT = 3000;

// app.listen(PORT, function(err) {
//     if(err) console.log(err);
//     console.log(`Server is listening on port ${PORT}`)
// })

const api = 'https://www.breakingbadapi.com/api/characters/?limit=20';

router.get("/", function(req, res) {
    https.get(api, (response) => {
        console.log(response.statusCode);
        
        response.on('data', (d) => {
            const data = JSON.parse(d);
            res.send(data);
        })

        // res.send("Running")
    })
})

module.exports = router;

Here is my Characters.jsx file where I'm using Fetch

import React, {useEffect, useState} from 'react';
import Card from '@mui/material/Card';
import axios from 'axios';

export default function Character() {
    const [data, setData] = useState();

    useEffect(() => {
        fetch('/characters')
            .then(res => res.json())
            .then(data => setData(data))
            // console.log(data);
    }, []);


}

When I run my front end and check the response I receive, it returns my index.html. If I fetch the API URL itself, then it correctly returns the JSON in my frontend. But When I try to fetch the API endpoint I created in express, I don't get any data. Any suggestions?

CodePudding user response:

You did not set the endpoint for the fetch function. It doesn't know what API '/characters' is. It is similar to saying the house number but not telling the street, you don't know where to go. So you need to pass the absolute path to fetch to request data from you the server, because the server is a different 'entity', it's not the same with your front-end. Therefore, you need to provide the full API URL. Or, if using axios, since I see you imported it above, you must set axios.defaults.baseURL = <API_URL>, (or provide the full URL in the request itself just like in fetch) and then make the request with the help of axios, not fetch.

Therefore your React code will look a little something like this:

import React, {useEffect, useState} from 'react';
import Card from '@mui/material/Card';
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:3000';

export default function Character() {
    const [data, setData] = useState();

useEffect(() => {
   const getData = async () => {
       try {
          const {data} = await axios.get('/characters');
          setData(data);
       } catch (err) {
          console.error(err);
       }
     };

    getData();
}, []);


}

But I suggest you create a different file with all the axios requests and there you set the baseUrl - that's a better practice.

CodePudding user response:

Error pattern

This kind of error occurs when we send a request from the client-side to the server-side using a relative URL (/characters in this case). But the frontend app and the backend app run on 2 different ports.

Reason

When we use relative URLs, the URL will be concatenated with the current host (the frontend host, not the backend). Usually, we receive a 404 error because the resource doesn't exist.

Example

Backend Express app running on port 5000. React app running on port 3000 for development. In React app, if we send a request to /users, then the full URL is http://localhost:3000/users. The request goes to the React app, not the backend server. And we don't receive the desired output.

Action

You should use an absolute URL, something like: http://localhost:5000/users to send the request to your backend app. Consider saving the host part (http://localhost:5000) in a global variable in order to use it in multiple places in your frontend code. When you have different environments for the backend (DEV/STAGING/PRODUCTION), you can change the backend host in only 1 place.

CodePudding user response:

I think is that you are not using cors in your app.

const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());

Try this, I hope it helps you!

  • Related