Search code examples
node.jsreactjsexpressnetlify

Network error from using localhost when web app is launched with Netlify


I just deployed a Spotify web app with Netlify. It works fine when it's running on my computer but it doesn't work on others. It shows Network Error, POST http://localhost:4000/search_result net::ERR_CONNECTION_REFUSED. I changed the url of the axios request to "/search_result" but it still didn't work. How should I fix it?

Here's my code.

Main.js

import React, { Component } from "react";
import SingerBox from "./SingerBox";
import axios from "axios";
import "../../App.css";

export class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      keyword: "",
      artists: [],
    };

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

  handleChange(e) {
    this.setState({ keyword: e.target.value });
  }

  handleSubmit(e) {
    e.preventDefault();
    if (this.state.keyword === "") {
      alert("Enter Search Keyword");
    }
    axios
      .post(
        "/search_result",
        {
          keyword: this.state.keyword,
        },
        {
          headers: {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": "*",
          },
        }
      )
      .then((res) => {
        this.setState({ artists: res.data });
      })
      .catch((err) => {
        console.log(err);
      });
  }

  render() {
    return (
      <div className="container">
        <div className="main">
          <form onSubmit={this.handleSubmit}>
            <label className="header" htmlFor="search">
              Explore New Artists
            </label>
            <span>
              <input
                className="search-box"
                type="search"
                value={this.state.keyword}
                onChange={this.handleChange}
                name="keyword"
                placeholder="Search artists..."
              />

              <button className="submit-btn" type="submit" value="Submit">
                Search
              </button>
            </span>
          </form>
          <br />

          {this.state.artists.map((elem) => (
            <SingerBox images={elem.images} name={elem.name} id={elem.id} />
          ))}

          <br />
        </div>
      </div>
    );
  }
}

export default Main;

server.js

const express = require("express");
const SpotifyWebApi = require("spotify-web-api-node");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const port = 4000 || process.env.PORT;

require("dotenv").config();

app.use(express.json());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));

// Create the api object with the credentials
var spotifyApi = new SpotifyWebApi({
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
});

// Retrieve an access token.
function newToken() {
  spotifyApi.clientCredentialsGrant().then(
    function (data) {
      console.log("The access token expires in " + data.body["expires_in"]);

      // Save the access token so that it's used in future calls
      spotifyApi.setAccessToken(data.body["access_token"]);
    },
    function (err) {
      console.log("Something went wrong when retrieving an access token", err);
    }
  );
}

newToken();

tokenRefreshInterval = setInterval(newToken, 1000 * 60 * 60);

app.post("/search_result", (req, res) => {
  spotifyApi
    .searchArtists(req.body.keyword)
    .then(function (data) {
      let search_res = data.body.artists.items;
      res.json(search_res);
      res.end();
    })
    .catch((err) => {
      console.log(err);
      res.status(500).send(err);
    });
});

app.get("/albums/:id", (req, res) => {
  console.log(req.params.id);
  spotifyApi
    .getArtistAlbums(req.params.id, { limit: 40 })
    .then(function (data) {
      res.json(data.body.items);
      res.end();
    });
});

app.get("/albums/tracks/:albumID", (req, res) => {
  console.log(req.params.albumID);
  spotifyApi
    .getAlbumTracks(req.params.albumID, { limit: 20 })
    .then(function (data) {
      console.log(data.body);
      res.json(data.body.items);
      res.end();
    });
});

app.listen(port, () => console.log(`It's running on port ${port}`));


Solution

  • It is likely that the server code isn't running as you expect it to. Think about what commands you run to get that localhost server running on your machine, compared to the build command you provided o Netlify to build your site.

    Netlify is primarily for hosting static sites, so will not automatically provide a backend server for you to use.

    You can either host the server part of your app on something like Heroku (and then have to hard-code the URL of that server instance into your app), or you can use Netlify Functions to handle your basic post request, which will let you use the relative URLs as in your question.