React/Express App when deployed to Heroku only responds with index.html - node.js

I'm attempting to deploy my first react + express app. It works locally and runs both the front end and backed on port 8080. However when I deploy to heroku, the backend only responds with index.html. I've tried changing the scripts in package.json and the paths in server.js but I'm pretty stuck in terms of getting more information out of this error and what to try next. When I first deployed to heroku I received an H10 error, but then following an article recommendation I installed serve. That package resolved the H10 error, but the app doesn't respond with the json from the database. What am I missing here?
https://runtopia.herokuapp.com/
Package.json
{
"name": "runtopia",
"version": "0.1.0",
"private": true,
"dependencies": {
"#amcharts/amcharts4": "^4.9.26",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"express": "^4.17.1",
"lodash": "^4.17.15",
"moment": "^2.26.0",
"nedb": "^1.8.0",
"nodemon": "^2.0.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"serve": "^11.3.2"
},
"scripts": {
"dev": "react-scripts start",
"start": "serve -s build",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"heroku-postbuild": "npm run build"
},
"proxy": "http://localhost:8080/",
"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"
]
}
}
server.js
const express = require('express');
const path = require('path')
const app = express();
const port = process.env.PORT || 8080;
const Datastore = require('nedb');
// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));
app.use(express.json());
// ADDED TO WORK FOR HEROKU
app.use(express.static(path.join(__dirname,'build')));
//retrieve data from database
app.get('/chartData', (request,response) => {
db.find({},(err,data) => {
if (err){
response.end();
return
}
response.json(data)
})
})
const db = new Datastore({filename:'./database.db', autoload: true});
app.post('/fitData', (request, response) => {
const fitData = request.body
fitData.map(week =>
{
console.log("logging week",week.weekYear)
db.update({'weekYear' : week.weekYear}, week, {upsert: true, multi: true}, function (){});
})
response.json({status: "this is the backend saying, got the lastest fitbit Data!"})
})
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.js
import React from 'react';
import Chart2 from './Chart';
import './App.css';
import moment from 'moment';
import _ from 'lodash';
class App extends React.Component{
constructor(props){
super(props)
this.state = {
fitData:[],
chartData: [],
}
this.grab = this.grab.bind(this);
this.queryDb = this.queryDb.bind(this)
}
//populates chart with data currently in db
componentDidMount(){
this.queryDb()
}
async post(){
const options = {
method: 'POST',
headers: {
'Content-Type' : 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(this.state.fitData)
}
const response = await fetch('/fitData', options);
const data = await response.json()
console.log(data)
await this.queryDb()
}
async queryDb(){
const response = await fetch('/chartData');
const dbData = await response.json()
let sorted = dbData.sort((a, b) => (a.date > b.date) ? 1 : -1)
this.setState({chartData:sorted})
}
render(){
return (
<div className="grid-container">
<div className="Top"></div>
<div className="Title">
<p className="runtopia">RUNTOPIA.</p>
<div>
<button className="big-button" onClick= {this.grab}>Get Data</button>
</div>
</div>
<div className="Weekly">
<Chart2 key={this.state.chartData} data={this.state.chartData} />
</div>
<div className="Bottom"></div>
</div>
);
}
}
export default App;

Related

Netlify / React front end not connecting to Node.js / Express / MongoDB Atlas / Heroku backend but works in development/locally

FIX: after following some advice I ditched the setupProxy and put the full API urls into the axios request. This threw a cors error so I imported CORS & added app.use(cors()) into my index.js & when I redeployed the app ran as intended
I am trying to deploy a MERN stack practise project for the first time. I am quite a new coder.
My project works perfectly fine in development/locally. My React app running on localhost:3000 connects to the Node/Express/MongoDB Atlas API that I deployed to Heroku & can make requests successfully.
However when I open the deployed Netlify app it fails to load any data & the Heroku logs show no activity which suggests it's not connecting to the backend at all.
Here are some bits of code that may be relevant:
-----------Backend---------------
environment.js (info in <> redacted)
export const dbURI = process.env.MONGODB_URI || 'mongodb+srv://<name>:<password>#festivalist.iyq41.mongodb.net/festivalist?retryWrites=true&w=majority'
export const port = process.env.PORT || 4000
export const secret = process.env.SECRET || '<secret>'
index.js
import express from 'express'
const app = express()
import mongoose from 'mongoose'
import router from './config/router.js'
import { port, dbURI } from './config/environment.js'
const startServer = async () => {
try {
await mongoose.connect(dbURI, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true })
console.log('πŸš€ Database has connected successfully')
app.use(express.json())
app.use((req, _res, next) => {
console.log(`🚨 Incoming request: ${req.method} - ${req.url}`)
next()
})
app.use('/api', router)
app.listen(port, () => console.log(`πŸš€ Express is up and running on port ${port}`))
} catch (err) {
console.log('πŸ†˜ Something went wrong starting the app')
console.log(err)
}
}
startServer()
package.json
{
"name": "sei-project-three",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"bcrypt": "^5.0.1",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongo": "^0.1.0",
"mongoose": "^5.12.0",
"nodemon": "^2.0.14"
},
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"seed": "node db/seeds.js",
"dev": "nodemon",
"start": "node index.js"
},
"devDependencies": {
"eslint": "^7.22.0"
},
"engines": {
"node": "16.8.0"
}
}
-------------Front end --------------
setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function (app) {
app.use(createProxyMiddleware('/api', { target: 'https://festivalist-api.herokuapp.com', "changeOrigin": true }))
}
example request
const ArtistIndex = () => {
const [artists, setArtists] = useState([])
useEffect(() => {
const getData = async () => {
const { data } = await axios.get('/api/artists')
setArtists(data)
}
console.log('artists2', artists)
getData()
}, [])
package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.21.1",
"http-proxy-middleware": "^1.0.5",
"mapbox-gl": "^2.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-map-gl": "^5.2.5",
"react-mapbox-gl": "^5.1.1",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"sass": "^1.42.1",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^2.0.3"
},
"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"
]
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^4.25.0",
"#typescript-eslint/parser": "^4.25.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.27.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.7.2",
"eslint-plugin-import": "^2.23.3",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0"
}
}
Some notes:
I have whitelisted all IP addresses in MongoDB Atlas 0.0.0.0/0
I'm unsure why but I have to put '/api/' on the end of the heroku api url to get the data ie: https://festivalist-api.herokuapp.com/api/festivals
I added Config Vars in Heroku but I think that stopped my app from working locally so I deleted them. Also not fully sure I understand what they do.
I have been trying to deploy this for days now so any advice would be a help or any troubleshooting tips since I am new to coding! Thanks
You have to put '/api' in at the end of heroku API because that's what you've used in your backend index.js app.use('/api', router)
The problem seems like something to do with the middle-wear setupProxy.js since you can ping the API already. One workaround is to just update your requests to use the full URI. i.e
const ArtistIndex = () => {
const [artists, setArtists] = useState([])
useEffect(() => {
const getData = async () => {
const { data } = await axios.get('https://festivalist-api.herokuapp.com/api/artists')
setArtists(data)
}
console.log('artists2', artists)
getData()
}, [])

when i deploy mern on heroku deploy problem in NODE_ENV

every thing is ok but when we write the code in this format
only show api call in formate of json or send but not show the react template
i can't undersatnd
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
const NODE_ENV = process.env.NODE_ENV || "devlopment"
const path = require("path");
var cors = require('cors')
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
app.get('/', (req, res) => {
res.json({
message: "Mern Deploy secces"
})
})
app.get('/sample', (req, res) => {
res.send("Hello Express");
})
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"))
app.get(" * ", (req, res) => {
res.sendFile(path.resolve(__dirname, "../client", "build", "index.html"))
});
console.log('production modde')
}
app.listen(port, () => {
console.log('server is running on 5000')
})
this is my node js file if i write the code in this formate
only show react js not show api request
index.js
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
const NODE_ENV = process.env.NODE_ENV || "devlopment"
const path = require("path");
var cors = require('cors')
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"))
app.get(" * ", (req, res) => {
res.sendFile(path.resolve(__dirname, "../client", "build", "index.html"))
});
console.log('production modde')
}
app.get('/', (req, res) => {
res.json({
message: "Mern Deploy secces"
})
})
app.get('/sample', (req, res) => {
res.send("Hello Express");
})
app.listen(port, () => {
console.log('server is running on 5000')
})
This is my React js File
import Raact, { useEffect ,useState } from 'react';
import './App.css';
import axios from 'axios';
function App() {
const [show, setshow] = useState("")
useEffect(()=>{
axios.get('/',)
.then((result)=>{
setshow(result.data.message)
}).catch((err)=>{
console.log(err)
})
},[])
return (
<div className="App">
<h1>Hello world</h1>
<h1>{show}</h1>
</div>
);
}
export default App;
client package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^5.11.10",
"#testing-library/react": "^11.2.6",
"#testing-library/user-event": "^12.8.3",
"axios": "^0.21.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "http://localhost:5000/"
}
package.json server
{
"name": "MERN-DEPLOY",
"version": "1.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": "14.15.5",
"npm": "7.5.4"
},
"scripts": {
"start": "node server/index.js",
"backend": "nodemon server/index.js",
"fontend": "npm run front --prefix client",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client ",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"nodemon": "^2.0.7"
}
}

Stripe - Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmCardPayment

Console Error message: v3:1 Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a client secret of the form ${id}_secret_${secret}. You specified: .
You can see the error yourself here: https://stormy-forest-38471.herokuapp.com/
Instructions to get error: From the main page, click on MenΓΊ Diari -> Demanar -> Any of the first 3 buttons -> Select one radio button from each category and then click on Afegeix i paga -> Pagar -> 1st input: 'Random Name', 2nd input: 'Recollida a tenda - Cabrera de Mar', 4th input: '123'...
Then, according to Stripe documentation, you could fill the payment element with the following data in order to achieve a successfull test payment.
Visa Number: '4242 4242 4242 4242'
MM/AA: '04/24'
CVC: '123'
Once you press Pagar, you will get the IntegrationError I'm asking for in the console.
I am trying to deploy a React.js + Node.js + Express web using Heroku.
I have been following this guide, although I am not sure if that's what I need.
https://blog.heroku.com/deploying-react-with-zero-configuration
The web is for a restaurant. They want to sell different lunch plans. I am trying to implement the payment using Stripe. When I test the app in my localhost, everything works fine. However, when I try to deploy it, something breaks.
I guess something must be wrong with my server.js or package.json files... The main problem being that I am a complete noob at Back End...
Everything works as expected (I still have some console logs here and there for development), until I start making requests to the server.
This is my server.js
const { createServer } = require('https');
const express = require('express');
const compression = require('compression');
const morgan = require('morgan');
const path = require('path');
const normalizePort = (port) => parseInt(port, 10);
const PORT = normalizePort(process.env.PORT || 5000);
const app = express();
const dev = app.get('env') !== 'production';
if (!dev) {
app.disable('x-powered-by');
app.use(compression()); // "Will handle a few things for us... (?)"
app.use(morgan('common'));
app.use(express.static(path.join(__dirname, 'build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
});
}
const server = createServer(app);
const { resolve } = require('path');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.use(express.json());
const calculateOrderAmount = (items) => {
console.log(items);
let drinksTotal = 0;
const { water, cola, colaZero, beer, lemonFanta, orangeFanta } = items.drinks;
drinksTotal += water * 100;
drinksTotal += (cola + colaZero + lemonFanta + orangeFanta) * 130;
drinksTotal += beer * 150;
let foodTotal = 0;
foodTotal += items.primerSegonCount * 895;
foodTotal += items.dosPrimersCount * 795;
foodTotal += items.platPostresCount * 695;
grandTotal = parseInt(drinksTotal + foodTotal);
console.log(grandTotal);
return grandTotal;
};
app.post('/create-payment-intent', async(req, res) => {
const { items } = req.body;
console.log(items);
// Create a PaymentIntent with the order amount and currency
const paymentIntent = await stripe.paymentIntents.create({
amount: calculateOrderAmount(items),
currency: 'eur'
});
res.send({
clientSecret: '123_secret_123' //paymentIntent.client_secret
});
});
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
server.listen(PORT, (err) => {
if (err) throw err;
console.log('Server started on port ' + PORT);
});
This is my package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"engine": {
"node": "12.16.3",
"npm": "6.14.5"
},
"dependencies": {
"#stripe/react-stripe-js": "^1.1.2",
"#stripe/stripe-js": "^1.7.0",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"boostrap": "^2.0.0",
"bootstrap": "^4.5.0",
"compression": "^1.7.4",
"concurrently": "^5.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"emailjs-com": "^2.4.1",
"express": "^4.17.1",
"morgan": "^1.10.0",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.0",
"react-scripts": "3.4.1",
"react-scroll": "^1.7.16",
"react-stripe-checkout": "^2.6.3",
"reactstrap": "^8.5.1",
"stripe": "^8.67.0",
"uuid": "^8.2.0",
"uuidv4": "^6.1.1"
},
"scripts": {
"start": "react-scripts start",
"start-dev": "nodemon server.js",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "concurrently \"npm run-script start-dev\" \"npm run-script start\"",
"heroku-postbuild": "npm install && npm run build"
},
"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"]
},
"homepage": "."
}
This is the React.js file in charge of the payment
import React, { useState, useEffect } from 'react';
import { CardElement, useStripe, useElements } from '#stripe/react-stripe-js';
// Bootstrap
import { Container, Row, Col, Button, Spinner, Form } from 'react-bootstrap';
export default function CheckoutForm(props) {
const [ succeeded, setSucceeded ] = useState(false);
const [ error, setError ] = useState(null);
const [ processing, setProcessing ] = useState(false);
const [ disabled, setDisabled ] = useState(true);
const [ clientSecret, setClientSecret ] = useState('');
const stripe = useStripe();
const elements = useElements();
useEffect(() => {
console.log('inside use Effect');
// Create PaymentIntent as soon as the page loads
window
.fetch('/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
items: {
drinks: props.drinksOrdered,
primerSegonCount: props.primerSegonCount,
dosPrimersCount: props.dosPrimersCount,
platPostresCount: props.platPostresCount
}
})
})
.then((res) => {
console.log(res);
return res.json();
})
.then((data) => {
console.log(data.clientSecret);
console.log(data);
setClientSecret(data.clientSecret);
});
}, []);
const cardStyle = {
base: {
backgroundColor: 'white',
color: 'grey',
fontFamily: 'Montserrat, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#c6c6c6'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
},
complete: {
color: 'green',
iconColor: 'green'
}
};
const handleCardChange = async (event) => {
// Listen for changes in the CardElement
// and display any errors as the customer types their card details
setDisabled(event.empty);
setError(event.error ? event.error.message : '');
};
const handleSubmit = async (ev) => {
ev.preventDefault();
setProcessing(true);
const payload = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
billing_details: {
name: ev.target.name.value
}
}
});
// Handle Error
if (payload.error) {
setError(`Payment failed ${payload.error.message}`);
setProcessing(false);
} else if (payload.paymentIntent.status === 'succeeded') {
// If payment succeeded, send eMail with details
props.sendEmail();
setSucceeded(true);
setError(null);
setTimeout(() => {
window.location.replace('https://www.cateringroser.cat');
}, 10000);
}
};
Thank you so much in advance.
Gerard
Well, as I guessed, I had to figure this one out myself. :-)
If you go back to my original post, you will be able to see the code I had for my server.js, package.json and CheckoutForm.jsx files.
The CheckoutForm.jsx was ok. Below you can see the modified versions of the code for:
server.js
const express = require('express');
const path = require('path');
const app = express();
const { resolve } = require('path');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.use(express.static(path.join(__dirname, 'build')));
app.use(express.json());
// app.use(express.json());
const calculateOrderAmount = (items) => {
let drinksTotal = 0;
const { water, cola, colaZero, beer, lemonFanta, orangeFanta } = items.drinks;
drinksTotal += water * 100;
drinksTotal += (cola + colaZero + lemonFanta + orangeFanta) * 130;
drinksTotal += beer * 150;
let foodTotal = 0;
foodTotal += items.primerSegonCount * 895;
foodTotal += items.dosPrimersCount * 795;
foodTotal += items.platPostresCount * 695;
grandTotal = parseInt(drinksTotal + foodTotal);
console.log(grandTotal);
return grandTotal;
};
app.post('/create-payment-intent', async(req, res) => {
const { items } = req.body;
// Create a PaymentIntent with the order amount and currency
const paymentIntent = await stripe.paymentIntents.create({
amount: 100, //calculateOrderAmount(items),
currency: 'eur'
});
res.send({
clientSecret: paymentIntent.client_secret
});
});
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT || 8080);
package.json
{
"name": "my-app",
"version": "1.0.0",
"description": "take away restaurant app",
"private": true,
"engines": {
"node": "12.x"
},
"dependencies": {
"#stripe/react-stripe-js": "^1.1.2",
"#stripe/stripe-js": "^1.7.0",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"boostrap": "^2.0.0",
"bootstrap": "^4.5.0",
"concurrently": "^5.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"emailjs-com": "^2.4.1",
"express": "^4.17.1",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"react-scroll": "^1.7.16",
"react-stripe-checkout": "^2.6.3",
"reactstrap": "^8.5.1",
"stripe": "^8.67.0"
},
"scripts": {
"start": "node server.js",
"start-dev": "nodemon server.js",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "concurrently \"npm run-script start-dev\" \"npm run-script start\"",
"heroku-postbuild": "npm install && npm run build"
},
"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"]
}
}
I ended up using what I knew on server.js. I deleted everything I didn't understand and kept the original code.
One of the most important things was to understand what happens when you deploy an app using node/express (or at least I think I understand).
First, I thought I needed to deploy both the Front and Back End sepparately, and then link them somehow.
What (I think) I really needed to do was to serve the Front End files from the server. In my first attempts to deploy, I was really serving them from React directly, so all I was getting was an interactive painting, in which I could navigate, but hadn't the opportunity to communicate with the server (since it was not connected).
What was the solution?
Serve the /build folder and it's files as explained in React's documentation on deployment.
Remove the "proxy": "http://localhost:5000" from package.json. Also remove "homepage":"xxx" if you had so.
Add "start": "node server.js" to your package.json. You want to open your web through node.
I also added a Procfile as recommended in Heroku's best practices for deployment with Node.js. All I have in the file is the following code: web: node server.js.
It just makes sense now. I can accept payments and communicate with my server.
As a sidenote: I didn't delete any of the Stripe specific code in my server.js, since it might help other users using Stripe to handle payments.
use secret key instead of public key in index.js in functions folder.

Deploy React with Heroku

Hi i'm trying to deploy my project with heroku but it's impossible i don't understand
I already did like that on other project but this time it doesn't works in my server.js i have this code :
const express = require("express");
const graphqlHTTP = require("express-graphql");
const cors = require("cors");
const schema = require("./schema");
const path = require("path");
const app = express();
//allow Cross origin
app.use(cors());
app.use(
"/graphql",
graphqlHTTP({
schema,
graphiql: true
})
);
app.use(express.static('public'));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
In my app.js who is in my Client folder i modify uri for AplolloClient :
import React from 'react';
import './App.css';
import Logo from "./logo.png";
import Matchs from './components/Matchs'
import MatchDetail from './components/MatchDetail'
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "#apollo/react-hooks";
import { BrowserRouter as Router, Route } from "react-router-dom";
const client = new ApolloClient({
uri: "/graphql"
});
function App() {
return (
<ApolloProvider client={client}>
<Router>
<div className="container">
<img
src={Logo}
alt="Nba App"
style={{ width: 300, display: "block", margin: "auto" }}
/>
<Route exact path="/" component={Matchs} />
<Route exact path="/match/:gameId" component={MatchDetail} />
</div>
</Router>
</ApolloProvider>
);
}
export default App;
in my package.json from my client folder i add a proxy :
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#apollo/react-hooks": "^3.1.3",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"apexcharts": "^3.15.5",
"apollo-boost": "^0.4.7",
"classnames": "^2.2.6",
"graphql": "^14.6.0",
"lodash.flowright": "^3.5.0",
"react": "^16.12.0",
"react-apexcharts": "^1.3.6",
"react-apollo": "^3.1.3",
"react-dom": "^16.12.0",
"react-icons": "^3.9.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && mv build ../public",
"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"
]
},
"proxy": "http://localhost:5000"
}
And i made a script to build and move in public/build
But when i deploy in heroku i have always
VM165:1 POST http://localhost:4000/graphql net::ERR_CONNECTION_REFUSED
But i don't know where he take this Url because i think i change all places where it could be problematic
Thanks a lot

How to fetch data from node server

I'm new to react and node and I'm trying to build a simple app to retrieve stock prices.
I'm able to reach my server route that I want but I'm getting a FetchError: invalid json response body from my server, what does this mean? How should I properly fetch an external api in my express route and send that data as a response?
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = {
response: '',
symbol: '',
};
handleSubmit = async e => {
e.preventDefault();
let apiURL = `/stocks/${ this.state.symbol }/price`
fetch(apiURL)
.then(res => res.json())
.then( (result) => {
this.setState({
response: result
})
})
};
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
</header>
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.symbol}
onChange={e => this.setState({ symbol: e.target.value })}
/>
<button type="submit">Submit</button>
</form>
<p>{this.state.response}</p>
</div>
);
}
}
export default App;
server.js
const express = require('express')
const path = require('path')
const bodyParser = require('body-parser')
const fetch = require('node-fetch');
const app = express()
const port = process.env.PORT || 5000
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
// API routes
app.get('/stocks/:symbol/price', (req, res) => {
const token = 'pk_5f69bda1e3074237a9d2e844a3dafbff'
const symbol = req.params.symbol
const apiURL = `https://sandbox.iexapis.com/stable/stock/${symbol}/price?token=${token}`
fetch(apiURL)
.then(res => res.json())
.then(data => {
res.send({ data })
})
})
app.listen(port, () => console.log(`Listening on port ${port}`))
package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.19.0",
"body-parser": "^1.18.3",
"express": "^4.16.4",
"node-fetch": "^2.6.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-scripts": "0.9.x"
},
"devDependencies": {
"concurrently": "^4.0.1",
"nodemon": "^1.9.2",
"ws": "3.3.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"client": "yarn start",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
},
"proxy": "http://localhost:5000/"
}

Resources