I successfully ran MERN app in my local machine using docker. Then, just for fun, I wanted it to deply to AWS, EC2 instance. After deploying, the fetch call in react-app gives this error:
GET http://localhost:5000/posts/ net::ERR_CONNECTION_REFUSED
App.js:37 TypeError: Failed to fetch
I am just creating and getting posts from react app which gets saved in mongodb. This works well in the local machine but not in the Amazon EC2 instance(Ubuntu 18.04), it doesn't work even though the frontend part is still showing but gives error when there is a api call.
I sshed the instance and tried curl command inside it, it gave the correct result. But using public url provided, i.e, from react app, gives above error.
Here are some details and hope you guys can help me.
React: App.js
import React from 'react';
import './App.css';
const serverUrl = 'http://localhost:5000'
const postModel = {
title: '',
body: '',
}
function App() {
const [posts, setPosts] = React.useState([])
const [post, setPost] = React.useState({ ...postModel })
React.useEffect(() => {
//get all the posts
fetch(`${serverUrl}`, {
method: 'GET',
})
.then(res => res.json())
.then(res => {
console.log(res)
})
.catch(err => console.log(err))
//get all the posts
fetch(`${serverUrl}/posts/`, {
method: 'GET',
})
.then(res => res.json())
.then(res => {
setPosts([...res])
})
.catch(err => console.log(err))
}, [])
const _postChange = (e) => {
setPost({ ...post, [e.target.name]: e.target.value })
}
const _addPost = () => {
//add new post
const requestJson = JSON.stringify(post)
console.log(requestJson)
fetch(`${serverUrl}/post/add/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: requestJson
})
.then(res => res.json())
.then(res => {
console.log(res)
setPosts([...posts, { title: res.post.title, body: res.post.body }]);
setPost({ ...postModel })
})
.catch(err => console.log(err))
}
console.log(post)
return (
<div className="App">
<h2>All Posts</h2>
<div>
<input placeholder="Post Title" value={post.title} onChange={_postChange} type="text" name="title" />
<input placeholder="Post body" value={post.body} onChange={_postChange} name="body" />
<button onClick={_addPost}>Add</button>
</div>
<div>
{posts.map((instance, index) => {
return <div key={index}>
<h4>{instance.title}</h4>
<p>{instance.body}</p>
<hr />
</div>
})}
</div>
</div>
);
}
export default App;
React: Dockerfile
# build environment
FROM node:12.2.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json /app/package.json
RUN npm install --silent
RUN npm install react-scripts#3.4.1 -g --silent
COPY . /app
RUN npm run build
# production environment
FROM nginx:1.16.0-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
React: package.json
{
"name": "react-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"cra-template": "1.0.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
backend: index.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const Post = require('./models/Post');
const cors = require('cors')
const app = express();
app.use(cors());
app.use(bodyParser.json());
// Connect to MongoDB
mongoose
.connect(
'mongodb://mongo:27017/node-mongo-docker',
{ useNewUrlParser: true }
)
.then(() => console.log('MongoDB is on'))
.catch(err => console.log(err));
//test the work
app.get('/', (req, res) => {
res.json({ 'message': 'Working properly' })
})
//get all posts
app.get('/posts', (req, res) => {
console.log("Getting of posts")
Post
.find()
.then(posts => res.json(posts))
.catch(err => res.json({ 'error': err }))
})
//post a new post
app.post('/post/add', (req, res) => {
console.log(req.body)
const newPost = new Post({
title: req.body.title,
body: req.body.body,
})
newPost
.save()
.then(post => res.json({ 'post': post }))
});
const port = 5000;
app.listen(port, () => console.log('Server is on'));
backend: Dockerfile
FROM node:12.2.0-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5000
CMD ["npm", "start"]
backend: package.json
{
"name": "node-mongo-docker",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"express": "^4.16.3",
"mongoose": "^5.2.7",
"nodemon": "^2.0.4"
}
}
docker-compose.yml
version: '3'
services:
react:
container_name: react-app
build: ./react-app
ports:
- '80:80'
links:
- server
server:
container_name: node-mongo-docker
restart: always
build: ./node-mongo
ports:
- '5000:5000'
links:
- mongo
# volumes:
# - '.:/usr/src/app'
mongo:
container_name: mongo
image: mongo
ports:
- '27017:27017'
You will need to replace "localhost" with the url of the deployed back-end.
React is a client-side javascript library, and runs in the users web browser, so it will use the "localhost" of the user that visits your page, not the server's localhost.
Related
Receiving an error: this interaction failed, none of my console logs are outputting besides the "logged in as". I have given the bot the correct token as well as permissions for admin, bot, and application.commands
here is my index.js file
const { Client, GatewayIntentBits, Events } = require('discord.js')
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.MessageContent
]
})
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
const options = [
'🐭',
'https://media.giphy.com/media/wJZTbXayokOgbCfyQe/giphy.gif',
'https://media.giphy.com/media/QXh9XnIJetPi0/giphy.gif',
'🐁',
];
client.on(Events.MessageCreate, message => {
console.log(message);
});
client.on(Events.InteractionCreate, interaction => {
console.log(`test1`);
if (!interaction.isCommand()) return;
console.log(`test3`);
if (interaction.commandName === 'hugging-face') {
console.log(`test3`);
interaction.reply(
options[Math.floor(Math.random() * options.length)]
);
}
});
client.login(process.env.TOKEN);
Here is my package.json
{
"name": "discord-slash-bot",
"version": "1.0.0",
"description": "package install",
"main": "index.js",
"scripts": {
"register": "node -r dotenv/config discord-slash-bot/register.js",
"start": "node -r dotenv/config index.js"
},
"keywords": [
"discord.js",
"#discordjs/rest",
"discord-api-types",
"dotenv"
],
"author": "conner",
"license": "ISC",
"dependencies": {
"#discordjs/rest": "^1.5.0",
"axios": "^1.2.3",
"discord-api-types": "^0.37.28",
"discord.js": "^14.7.1",
"dotenv": "^16.0.3"
}
}
Here is my register.js to register the commands
const { REST } = require('#discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const commands = [
{
name: 'hugging-face',
description: 'input images and prompt',
},
];
const rest = new REST({ version: '10' }).setToken(process.env.TOKEN);
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(Routes.applicationCommands(process.env.APP_ID), {
body: commands,
});
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
I'm not exactly sure what the issue was, but it seems like register.js isn't running if there aren't any logs and/or was run before changes were made. I would run:
npm install && npm run register && npm run start
'npm install' would reinstall your dependencies, in case it's a versioning issue, while
'npm run register' would run ./discord-slash-bot/register.js to refresh all of the commands.
Hope this helps; cheers!
1st problem (Local problem):
This is my first testing file:
const { InsertResult } = require('typeorm').InsertResult;
const {init, teardownDb, app} = require('../dist/api/index');
const User = require('../dist/db/entities/user.entity').User;
const datasource = require('../dist/db/connection').datasource;
const chai = require('chai');
const chaihttp = require('chai-http');
chai.use(chaihttp);
let server;
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
describe("Happy Tests for Users", () => {
beforeAll(async () => {
server = await init();
});
afterAll(async () => {
await server.close();
});
describe("Register User Tests", () => {
it("Happy Test", (done) => {
//jest.spyOn(datasource.createQueryBuilder().insert().into(User).values(Any), 'execute').mockImplementation(() => { return "test";})
chai.request(app)
.post('/users/register')
.send({address: "anaddress", username: "aname", password: "apassword"})
.end((err, res) => {
expect(err).toBe(null);
expect(res.status).toBe(200);
done();
});
});
});
describe("Register Coach Tests", () => {
it("Happy Test", (done) => {
chai.request(app)
.post('/users/registercoach')
.send({address: "coachaddress", username: "coachcole2", password: "apassword"})
.end((err, res) => {
expect(err).toBe(null);
expect(res.status).toBe(200);
done();
});
});
});
});
This is my second testing file:
const { InsertResult } = require('typeorm').InsertResult;
const {init, teardownDb, app, startListening} = require('../dist/api/index');
const User = require('../dist/db/entities/user.entity').User;
const datasource = require('../dist/db/connection').datasource;
const chai = require('chai');
const chaihttp = require('chai-http');
const bcrypt = require('bcrypt');
const express = require('express');
chai.use(chaihttp);
let server;
let pw;
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
describe("Happy Tests for Service", () => {
beforeAll(async () => {
server = await init();
});
beforeAll(async () => {
pw = await bcrypt.hash("apassword", 10);
});
beforeAll(async () => {
await datasource
.createQueryBuilder()
.insert()
.into(User)
.values({
address: "testaddress",
name: "testusername",
iscoach: false,
password: pw
})
.execute();
await datasource
.createQueryBuilder()
.insert()
.into(User)
.values({
address: "testcoachaddress",
name: "testcoach",
iscoach: true,
password: pw
})
.execute();
});
afterAll(async () => {
await datasource.destroy();
await server.close();
});
describe("Register Service Tests", () => {
it("Happy Test", (done) => {
chai.request(app)
.post('/services/requestRegisterService')
.send({address: "testaddress", name: "servicename.", description: "servicedesc.", password: "apassword"})
.end((err, res) => {
expect(err).toBe(null);
expect(res.status).toBe(200);
done();
});
});
});
describe("Admit Service Tests", () => {
it("Happy Test", (done) => {
//jest.spyOn(datasource.createQueryBuilder().insert().into(User).values(Any), 'execute').mockImplementation(() => { return "test";})
chai.request(app)
.post('/services/admitservice')
.send({address: "testcoachaddress", name: "servicename.", password: "apassword"})
.end((err, res) => {
expect(err).toBe(null);
expect(res.status).toBe(200);
done();
});
});
});
describe("Buy Service Tests", () => {
it("Happy Test", (done) => {
//jest.spyOn(datasource.createQueryBuilder().insert().into(User).values(Any), 'execute').mockImplementation(() => { return "test";})
chai.request(app)
.post('/services/buy')
.send({address: "testaddress", name: "servicename.", password: "apassword"})
.end((err, res) => {
expect(err).toBe(null);
expect(res.status).toBe(200);
done();
});
});
});
});
All the tests pass, but at the end of all the tests I am getting the following error from typeorm:
QueryFailedError: Connection terminated
I run the tests with runInBand because both tests are using the same webserver port and database.
2nd (probably related) Problem on the github runner:
For CI, I am using github actions. This is my actions file:
name: footballmarketplace
run-name: Backend and Frontend tests for footballmarketplace 🚀
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: ubuntu-latest
services:
postgres:
image: postgres:latest
env:
POSTGRES_USER: ${{ secrets.USERNAME }}
POSTGRES_PASSWORD: ${{ secrets.PASSWORD }}
POSTGRES_DB: ${{ secrets.DATABASE }}
ports:
- 5432:5432
env:
PORT: ${{ secrets.PORT }}
DBPORT: 5432
USERNAME: ${{ secrets.USERNAME }}
PASSWORD: ${{ secrets.PASSWORD }}
DATABASE: ${{ secrets.DATABASE }}
HOST: postgres
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout#v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- name: Build and run
working-directory: ./backend
run: |
npm install
npm run clean
npm run lint
npm run tsc
npm run test
Whereas this is my Package json:
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"scripts": {
"test": "nyc --reporter=text jest test/* --runInBand",
"lint": "tslint -c tslint.json -p tsconfig.json",
"dev": "NODE_ENV=dev node .",
"clean": "rimraf dist/*",
"tsc": "tsc",
"build": "npm-run-all clean lint prettier-format tsc swagger-autogen",
"dev:start": "npm-run-all build dev",
"start": "nodemon --watch src -e ts --exec npm run dev:start",
"prod": "npm run dev",
"docker": "docker run --rm -it $(docker build -q .)",
"prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write",
"swagger-autogen": "node ./src/api/swagger/swagger.cjs"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.0",
"ejs": "^3.1.8",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"http-status-codes": "^2.2.0",
"pg": "^8.9.0",
"reflect-metadata": "^0.1.13",
"swagger-ui-express": "^4.6.0",
"typeorm": "^0.3.11",
"winston": "^3.8.2"
},
"devDependencies": {
"#istanbuljs/nyc-config-typescript": "^1.0.2",
"#jest/globals": "^29.4.1",
"#types/bcrypt": "^5.0.0",
"#types/express": "^4.17.16",
"#types/mocha": "^10.0.1",
"#types/node": "^18.11.18",
"#types/pg": "^8.6.6",
"#types/shelljs": "^0.8.11",
"#types/swagger-ui-express": "^4.1.3",
"chai": "^4.3.7",
"chai-http": "^4.3.0",
"jest": "^29.4.2",
"nodemon": "^2.0.20",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"prettier": "^2.8.3",
"rimraf": "^4.1.2",
"swagger-autogen": "^2.23.0",
"ts-mockito": "^2.6.1",
"ts-node": "^10.9.1",
"tslint": "^6.1.3",
"typescript": "^4.9.4"
}
}
For the build part, I am getting the following errors: (i really dont understand why the runner cant find the close() function which is referring to the await close in the afterAll in jest):
getaddrinfo EAI_AGAIN ***
this.subQuery is not a function <- this is a typeorm error that means that datasource probably wasnt initialized the right way.
TypeError: Cannot read properties of undefined (reading 'close') <- this is the weirdest part. Does that mean that the server wasnt initialized correctly?
It may be relevant to say that this is a typescript project but the test are in javascript and are using the generated code in dist/
Sidenote: I am also not sure if it is a good pattern to run tests on a github runner that initialize a temporary webserver. Should the webserver be outsourced instead? Or atleast containerized like I did it with the database? Or is there another way to test an api from a webserver on a runner?
This is my package.json:
{
"name": "aracelli-v-photography-website",
"version": "0.0.3",
"private": true,
"description": "a photography website",
"main": "api/server.js",
"scripts": {
"start": "concurrently -p \"{name}\" -c \"green\" -n \"database,node\" \"npx sequelize-cli db:migrate --env=production\" \"HOSTING_DIR=livebuild/ node server\"",
"dev": "concurrently -p \"{time}-{name}\" -c \"green\" -n \"react,nodemon\" \"react-scripts build\" \"nodemon server\"",
"test": "concurrently -p \"{time}-{name}\" -c \"green\" -n \"database,node\" \"DATABASE_URL=$(heroku config:get DATABASE_URL -a aracelli-v-photography) npx sequelize-cli db:migrate --env=production\" \"DATABASE_URL=$(heroku config:get DATABASE_URL -a aracelli-v-photography) node server\"",
"build": "BASE_URL=\"https://aracelli-v-photography.herokuapp.com/api\" react-scripts build && rm -rf livebuild && mv build livebuild"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Aracelli-V-Photography/aracelli-v-photography-website.git"
},
"author": "jadelynnmasker",
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/Aracelli-V-Photography/aracelli-v-photography-website/issues"
},
"homepage": "/",
"devDependencies": {
"axios": "^0.21.1",
"eslint": "^7.28.0",
"nodemon": "^2.0.7",
"prettier": "^2.3.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.3",
"redux": "^4.1.0",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.3.0",
"uuid": "^8.3.2"
},
"dependencies": {
"bcrypt": "^5.0.1",
"concurrently": "^6.2.0",
"njwt": "^1.1.0",
"pg": "^8.6.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.6.2",
"sequelize-cli": "^6.2.0"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}My question is, why doesn't the server deploy with react
}
And my server.js:
const http = require("http");
const url = require("url");
const fs = require("fs");
const path = require("path");
const routes = require("./config/routes");
const PORT = process.env.PORT || 3000;
const HOME_DIRECTORY = process.cwd();
const STATIC_DIRECTORY = process.env.HOSTING_DIR || "build/";
const server = http.createServer(function (request, response) {
try {
process.chdir(HOME_DIRECTORY);
} catch (error) {
console.log(error);
}
if (request.url.split("/")[1] !== "api") {
const parsedUrl = url.parse(request.url);
let pathname = `.${parsedUrl.pathname}`;
const extension = path.parse(pathname).ext;
try {
process.chdir(STATIC_DIRECTORY);
} catch (error) {
return console.log(error);
}
const mapExtensionsToContentType = {
".ico": "image/x-icon",
".html": "text/html",
".js": "text/javascript",
".json": "application/json",
".css": "text/css",
".png": "image/png",
".jpg": "image/jpeg",
".wav": "audio/wav",
".mp3": "audio/mpeg",
".svg": "image/svg+xml",
".pdf": "application/pdf",
".doc": "application/msword",
};
fs.exists(pathname, function (exist) {
if (!exist) {
response.statusCode = 301;
response.setHeader("Location", "/");
return response.end(() => {
console.log(
"\nUser probably refreshed the page. Stand by for new session!"
);
});
}
if (pathname === "./") {
pathname += "index.html";
console.log("\nUser joined the site!");
}
fs.readFile(pathname, function (error, data) {
if (error) {
response.statsCode = 500;
response.end(`Error getting the file: ${error}`);
return console.error(`Error getting the file: ${error}`);
}
response.setHeader(
"Content-Type",
mapExtensionsToContentType[extension] || "text/html"
);
response.end(data);
});
});
} else {
const actionPath = `${request.method} ${request.url}`;
const route = routes.find(function (route) {
return actionPath.match(route[0]);
});
if (!route) {
return console.log(`\n${actionPath} -> undefined`);
}
console.log(`\n${actionPath} -> ${route[1]}`);
const [controllerName, method] = route[1].split("#");
const Controller = require(`./controllers/${controllerName}Controller`);
if (request.method !== "POST") {
const controller = new Controller(request, response);
controller[method]();
} else {
let body = "";
request.on("data", function (chunk) {
body += chunk.toString();
});
request.on("end", function () {
controller = new Controller(
request,
response,
JSON.parse(body)
);
controller[method]();
});
}
}
});
server.listen(PORT, function () {
console.log("Server running on port " + PORT);
});
Finally, my /src/redux/common.js, where I think the problem is:
import axiosBase from "axios";
import { v4 as uuidv4, v5 as uuidv5 } from "uuid";
export const axios = axiosBase.create({
baseURL: process.env.BASE_URL || "http://localhost:3000/api",
});
const NAMESPACE = uuidv4();
export function uuid() {
return uuidv5(uuidv4(), NAMESPACE);
}
Basically, I'm trying to host a Node.js server with more knowledge in React than in Node, and I'm stuck here because no matter what I do axios always sends requests to "http://localhost:3000/api". I need to deploy on heroku and have it send requests to heroku instead of my local machine! I looked at the docs for create-react-app and it looks like I am doing it right. I am, however, always using a production build of react because I couldn't figure out where to find the development build. Because of how it's deployed on heroku (my node server serves the react app as well as the api) I don't want my app running on two different ports and needing cors.
With that out of the way, there are basically two solutions to my problem that will make me happy. One is, I could find where the development build is and use the NODE_ENV enviromnent variable to determine whether I am on a server or not. Or, two, I could find a way to make the enviroment variables that I am using work.
Either way, I appreciate your time and consideration. If more information is needed, I will gladly post an update.
There is no problem with your app bro. You have made an error in your package.json. What you have done is include your dependencies in the devDependencies which means that react module is not being installed on your Heroku app.
During the deployment, you will notice that it shows a line pruning devDependencies which means that it's cutting the packages from the list which are in the devDependencies.
Steps to make things right:
You have to include your devDependencies in dependencies
To do so run this command
npm install axios react react-dom react-redux
react-router-dom react-scripts redux redux-devtools-extension redux-thunk uuid --save-prod
Now push your app to Heroku and it will start working.
I am trying to fetch data from my local express server, and display it with react, but it seems that the index.html of the react app is being returned. If I check the network tab in the console and it shows that there is a fetch request with the name "projects/" and when I hover over it it shows "http://localhost:3000/api/projects". The console indicates that the problem is in line 13 of the react file which is "fetch('/api/projects/')". I've been trying for a while to fix this but can't seem to get it right. Code below
Express:
const express = require("express");
const app = express();
app.use(express.json());
let projects = [
{
id: 1,
title: "project1",
description: "One - description",
url: "www.One.com"
},
{
id: 2,
title: "project2",
description: "Two - description",
url: "www.Two.com"
},
{
id: 3,
title: "project3",
description: "Three - description",
url: "www.Three.com"
}
];
app.get("/api/projects", (req, res) => {
res.json(projects);
});
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
React:
import React from "react";
import "./App.css";
class App extends React.Component {
constructor() {
super();
this.state = {
projects: []
};
}
componentDidMount() {
fetch("/api/projects/")
.then(res => res.json())
.then(projects =>
this.setState({ projects }, () =>
console.log("Projects fetched...", projects)
)
);
}
render() {
return (
<div className="App">
<h1>Projects</h1>
</div>
);
}
}
export default App;
React package.json:
{
"name": "my-full-stack-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [">0.2%", "not dead", "not op_mini all"],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Your server is running on port 5000 and the client on port 3000. So, you have to call the api request as
fetch('http://localhost:5000/api/projects/')
If you don't specify the full URL, the request will be sent to http://localhost:3000/api/projects
You can also store the base URL in a constant.
import React from 'react';
import './App.css';
const baseUrl = 'http://localhost:5000';
class App extends React.Component {
constructor() {
super();
this.state = {
projects: []
}
}
componentDidMount() {
fetch(`${baseUrl}/api/projects/`)
.then(res => res.json())
.then(projects => this.setState({ projects }, () => console.log('Projects fetched...', projects)));
}
render() {
return (
<div className="App">
<h1>Projects</h1>
</div>
);
}
}
export default App;
Seems it was a cross-origin request. I installed the cors middleware, following the steps in the expressjs documentation, and added it to my express file and used app.use(cors()). Everything works now!
Just throwing this in, I know this has been answered, but I encountered this problem and was spinning my wheels for a while on it, despite all the solutions. Here is how I figured out to make it work:
I was a bit confused about the ports to use, as the app opens in port 3000, even though I had specified 5000 for my Express server. So I changed all ports everywhere to 3000 to try it out.
then I restarted my server first, then my react app, and it asked me if I wanted to open it on another port because 3000 was already being used. I said yes, and viola, it works. It now opens on port 3001 and everything works beautifully.
Code below to help any who may come to this page later, like I did.
server.js (express):
const express = require('express');
const cors = require('cors');
const knex = require('knex');
const db = knex({
client: 'pg',
connection: {
host: "127.0.0.1",
user: "",
password: "",
database: "",
},
});
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// CORS implemented so that we don't get errors when trying to access the server from a different server location
app.use(cors());
// GET: Fetch all movies from the database
app.get('/', (req, res) => {
db.select('*')
.from('cards')
.then((data) => {
console.log(data);
res.json(data);
})
.catch((err) => {
console.log(err);
});
});
const port = 3000;
app.listen(port, () => console.log(`Server running on port ${port}, http://localhost:${port}`));
React App.js:
import React, { useState, useEffect } from 'react';
import './App.css';
const App = () => {
useEffect(() => {
const getAPI = () => {
const API = 'http://127.0.0.1:3000';
fetch(API)
.then((response) => {
console.log(response);
return response.json();
})
.then((data) => {
console.log(data);
setLoading(false);
setApiData(data);
});
};
getAPI();
}, []);
const [apiData, setApiData] = useState([]);
const [loading, setLoading] = useState(true);
return (
..... react stuff here .....
);
};
export default App;
This question already has an answer here:
Fetch error when building Next.js static website in production
(1 answer)
Closed 9 months ago.
I have an API route which upon request gets me the data I want when the Project page (component) is loaded as shown below.
http://localhost:3000/api/projects
When I load the page where I request for that data inside getInitialProps() within pages/projects.js it shows data coming through which is what I want as shown below, so far so good.
console logs data coming through from custom express API route I have made
The code for that is here:
pages/projects.js
import React, { Component } from "react";
import Layout from "../components/Layout";
import Siema from "siema";
import Head from "next/head";
import fetch from "isomorphic-unfetch";
export default class extends React.Component {
componentDidMount() {
this.siema = new Siema({
loop: false
});
}
prev = () => {
this.siema.prev();
};
next = () => {
this.siema.next();
};
render() {
return (
<Layout>
<Head>
<title>Jesal Patel | Projects</title>
</Head>
<div className="container">
<section>
<div className="projects">
<div className="siema">
<div>
<img src="(ignore this the img is showing on stackoverflow post.)" />
<div className="overlay">
<div id="overlay_title">Dextero</div>
<div id="overlay_description">
I developed a multi-touch mobile game for stroke patients
to rehabilitate their finger coordination and dexterity.
</div>
<div id="overlay_tech">Java, Android, LibGDX, SQLite</div>
</div>
</div>
</div>
<div />
<button onClick={this.prev}>Prev</button>
<button onClick={this.next}>Next</button>
</div>
</section>
</div>
</Layout>
);
}
static async getInitialProps({ req }) {
//This fetch is the reason why my project won't build
const result = await fetch("http://localhost:3000/api/projects");
const projects = await result.json();
console.log(projects);
return { projects };
}
}
The Problem:
Now the problem begins when I run next-build and the following error throws during it: EDIT: I didn't paste the error properly. NOTE: I run now-buildscript which exports the project and that's my problem, it's what's causing me problems
I:\Next.js\website>npm run now-build
> website#1.0.0 now-build I:\Next.js\website
> next build && next export -o dist
Creating an optimized production build ...
Compiled successfully.
┌ /
├ /_app
├ /_document
├ /_error
├ /contact
└ /projects
> using build directory: I:\Next.js\website\.next
copying "static" directory
copying "static build" directory
> No "exportPathMap" found in "next.config.js". Generating map from "./pages"
launching 11 threads with concurrency of 10 per thread
[====-] 4/5 80% 160/s 0.0s { FetchError: request to http://localhost:3000/api/projects failed, reason: connect ECONNREFUSED 127.0.0.1:3000
at ClientRequest.<anonymous> (I:\Next.js\website\node_modules\node-fetch\lib\index.js:1444:11)
at ClientRequest.emit (events.js:189:13)
at Socket.socketErrorListener (_http_client.js:392:9)
at Socket.emit (events.js:189:13)
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
message:
'request to http://localhost:3000/api/projects failed, reason: connect ECONNREFUSED 127.0.0.1:3000',
type: 'system',
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED' }
{ message:
'request to http://localhost:3000/api/projects failed, reason: connect ECONNREFUSED 127.0.0.1:3000',
type: 'system',
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED' }
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! website#1.0.0 now-build: `next build && next export -o dist`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the website#1.0.0 now-build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Jesal\AppData\Roaming\npm-cache\_logs\2019-03-19T04_10_45_930Z-debug.log
I understand that it's due to this line const result = await fetch("http://localhost:3000/api/projects");, but I don't know what to do to enable it to build. I am new to MEAN stack. I'm not sure if I have to create that route externally somewhere global for it to work fine? I don't know if that will fix it or if it's something else.
I have used Express and Mongoose with this application and the code for these can be found below along with the package.json and next.config.js files.
server/index.js
const express = require("express");
const next = require("next");
const bodyParser = require("body-parser");
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
const routes = require("./routes/index.js");
var mongoose = require("mongoose");
const PORT = process.env.PORT || 3000;
const dbName = "MySite";
const MONGO_URL =
"mongodb+srv://admin:<hidden for privacy>#cluster0-5cjs1.mongodb.net/MySite?retryWrites=true";
app
.prepare()
.then(() => {
mongoose.connect(MONGO_URL, { useNewUrlParser: true });
mongoose.Promise = global.Promise;
mongoose.connection.on("open", function() {
console.log("mongodb is connected!!");
});
const db = mongoose.connection;
model = db.modelNames();
db.on("error", console.error.bind(console, "MongoDB connection error:"));
const server = express();
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({ extended: true }));
server.use("/api", routes);
server.use((req, res, next) => {
// Also expose the MongoDB database handle so Next.js can access it.
req.db = db;
next();
});
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(PORT, () => {
console.log("Server is up and running on port number " + PORT);
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
server/routes/index.js
const express = require("express");
const router = express.Router();
const project_controller = require("../controllers/project_controller");
router.get("/projects", project_controller.projects_list);
module.exports = router;
server/models/project_schema.js
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ProjectSchema = new Schema(
{
name: String,
description: String,
tech: String
},
{ collection: "project" }
);
module.exports = mongoose.model("Project", ProjectSchema);
server/controllers/project_controller.js
const Project = require("../models/project_schema");
exports.test = function(req, res) {
res.send("Greetings from the Test controller!");
};
exports.projects_list = function(req, res) {
var documents = Project.find({}, function(err, docs) {
if (err) throw err;
res.send(docs);
return docs;
});
};
exports.project_create = function(req, res) {
let project = new Project({
name: req.body.name,
description: req.body.description,
tech: req.body.tech
});
project.save(function(err, project) {
if (err) {
console.log("Unsuccessful");
}
console.log("Saved!");
});
};
package.json
{
"name": "website",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "nodemon server/index.js",
"now-build": "next build && next export -o dist",
"build": "next build",
"start": "next start -p 8000"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"#engineerapart/nextscript": "^1.0.2",
"#zeit/next-css": "^1.0.1",
"#zeit/next-typescript": "^1.1.1",
"body-parser": "^1.18.3",
"bootstrap": "^4.3.1",
"co": "^4.6.0",
"cross-env": "^5.2.0",
"express": "^4.16.4",
"file-loader": "^3.0.1",
"isomorphic-unfetch": "^3.0.0",
"jquery": "^3.3.1",
"mongodb": "^3.1.13",
"mongoose": "^5.4.19",
"next": "^8.0.4-canary.10",
"next-compose-plugins": "^2.1.1",
"next-images": "^1.0.4",
"nodemon": "^1.18.10",
"react": "^16.8.3",
"react-dom": "^16.8.3",
"react-slick": "^0.23.2",
"siema": "^1.5.1",
"superagent": "^4.1.0",
"url-loader": "^1.1.2"
}
}
next.config.js
const withCSS = require("#zeit/next-css");
const withImages = require("next-images");
const withPlugins = require("next-compose-plugins");
module.exports = {
crossOrigin: "anonymous"
};
module.exports = withPlugins([withImages, withCSS]);
module.exports = withImages();
// module.exports = withCSS();
module.exports = {
target: "serverless"
};
module.exports = withCSS({
webpack: function(config) {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
name: "[name].[ext]"
}
}
});
return config;
}
});
UPDATE: This is an update to Prabhakar Pandey's response, to let you guys know, I always killed the server when running the now-buildcommand, Also, to be very clear as I mentioned before on my first edit of this post, that it's the 2nd part of that command which is failing with error, which is next export -o distnot next build, that works fine! Also, I'm on Windows OS not Mac OS.
This happens because you want to run an application on a port which is already being used.
you can check the application running on a port with these commands:
For macOS El Capitan and newer (or if your netstat doesn't support -p), use lsof
sudo lsof -i tcp:3000
For Centos 7 use
netstat -vanp --tcp | grep 3000
Also if wnat to kill any process you can use
kill -9 `PID`
when port is empty you try your application by rebuilding it should work