I'm trying to get information with a fetch (client) and a get (server) requests to get data from the server with the client and printing it.
for some reason I can't get the information I'm looking for and I think it has somthing to do with the url I'm entering, can I get an explanation, or maybe an example about the url I'm supposed to enter?
I'll enter my code as an example:
client:
//bitcoin page: url - 'http://localhost:3000/bitcoin'
//NOTE: the proxy is: 'http://localhost:3001'
import React from "react";
import { Link } from "react-router-dom";
function BitCoin() {
const [data, setData] = React.useState(null);
console.log("entered bitcoin page");
React.useEffect(() => {
fetch("NOT SURE WHAT TO WRITE HERE")
.then((res) => res.json())
.then((data) => setData(data.message));
}, []);
return (
<div style={{textAlign:"center", fontFamily:"Comic Sans MC", fontSize:"100"}}>
THIS IS THE BitCoin PAGE
<nav>
<Link to="/"> Home </Link>
</nav>
<nav>
<Link to="/coins"> Coins </Link>
</nav>
<p>{!data ? "Loading..." : data}</p>
</div>
)
}
export default BitCoin;
server:
//index.js: url - 'http://localhost:3001'
const express = require("express");
const PORT = process.env.PORT || 3001;
const app = express();
app.get('NOT SURE WHAT TO WRITE HERE', (req, res) => {
console.log("entered bitcoin query!");
let msg = "";
//some functions to get the msg I'm looking for (not relevant)
res.json({ message: msg });
});
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
as you can see there's a log when entering the get request but the console's not logging it, I'm guessing the client and the server are not communicating and that's what makes the problem.
thank you <3
It's important to understand the general architecture of your technology stack:
You have the React frontend running under http://localhost:3000. This is simply serving the React app through a development server on your computer.
Additionally, you have a NodeJS app (using express) running at http://localhost:3001. Notably, this runs under a different port to the React app.
In your express code, you would define a url which the React frontend can call, to fetch data. So let's call it /coin-message:
app.get('/coin-message', (req, res) => {
Now, in the React app, you can make ajax requests to this url:
fetch("http://localhost:3001/coin-message")
Note that you need to include the full URL and port in the fetch() - this is because the Node app runs under a different port.
Important
Because you want to make ajax requests to a URL which has a different port to the React app, you will encounter a Same Origin Policy problem. This is a security measure activated by browsers to prevent web app vulnerabilities. To solve this, you can use one of the CORS middlewares for express, such as this one.
server:
app.get('/bitcoin', ...)
client:
fetch('http://localhost:3001/bitcoin')
Related
Backend code example: I am trying to get users here from my SQL Server database Account:
async function executeQuery() {
try {
const pool = await sql.connect(config);
const result = await pool
.request()
.query(`USE Account SELECT TOP 10 UserNo FROM UserTable`);
return result;
} catch (err) {
console.log(err);
}
}
app.get("/api/data", async (req, res) => {
const result = await executeQuery();
res.json(result);
});
React frontend code: I am getting an error when try to render data from SQL Server.
import React, { useState, useEffect } from "react";
function SqlTest() {
const [data, setData] = useState([]);
async function fetchData() {
const result = await fetch("/api/data").then((res) => res.json());
setData(result);
}
useEffect(() => {
fetchData();
}, []);
return (
<div>
{data.map((item) => (
<div key={item.UserNo}>{item.UserNo}</div>
))}
</div>
);
}
export default SqlTest;
I am trying to render data from SQL Server, but nothing helps..
Ok, your problem is a very common one that has a very common solution.
You have 2 separate projects (HTTP servers):
The HTTP server that CRA comes with, which is a NodeJS server.
Your API server, which happens to also be a NodeJS server.
Now you want to fetch data from React by querying your API server.
Look at your URL: api/data. This is a relative URL. Relative URL's are resolved by the browser by using the current page's domain. I don't know your exact setup, but the URL will end up being something like http://localhost:3000/api/data.
Do you see the problem already? Your API server is not listening on port 3000. It is probably listening on some other port number. After all, no 2 applications can listen on the same TCP port.
So you would then be tempted to change your fetch URL to a full URL that specifies the server API: http://localhost:3001/api/data. That probably works, but there's a chance it errors out due to CORS.
So long story short, do as the CRA help pages say you should do: Set a proxy up in your CRA server. Here it is: https://create-react-app.dev/docs/proxying-api-requests-in-development/
In a nutshell, create the file src/setupProxy.js with code similar to this:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000', // <-- USE YOUR API PORT
changeOrigin: true,
})
);
};
The sample assumes you're running your API server in port 5000. Change it to fit your configuration.
I am trying to create a simple react app with node/express for the backend. When I start my app I get this error:
Proxy error: Could not proxy request /users from localhost:3000 to http://localhost:5000/.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
My front-end package.json looks like this
The front-end is pretty simple. fetchUserData() under useEffect() is what calls the backend.
import React, { useEffect, useState } from "react";
function App() {
let [userData, setUserData] = useState([{}]);
useEffect(() => {
const fetchUserData = async () => {
const response = await fetch(`/users`);
const data = await response.json();
setUserData(data);
};
fetchUserData();
}, []);
return (
<div>
<h1>Hello React World!</h1>
</div>
);
}
export default App;
The backend is pretty barebone as I just started this project. I have no problem getting the correct response if I just request http://localhost:5000/users directly from the browser or postman:
const express = require("express");
const app = express();
const port = process.env.PORT || 5000;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/users", (req, res) => {
console.log(req);
res.json({ users: ["Bob", "Sally"] });
});
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
The error message appears when I try to load the front end on http://localhost:3000 which should then fetch the backend resource. I look at the network tab of chrome and for some reason it is going to port 3000 instead of 5000:
I've tried the below but no luck:
Closing my app. Deleting package-lock.json and node_modules, reinstalling them.
Add '/' to the end of the string for the "proxy" setting in package.json
Replacing localhost with 127.0.0.1 in package.json
Tried adding "--ignore client" to dev script in server package.json
Tried adding "secure": false in client package.json
Edit 1: This issue is driving me crazy. If I remove the proxy from package.json, add cors to the server side, and use the absolute path of the endpoint instead of the relative path in my client-side fetch request, it works. But I would much rather use the relative path.
import React, { useEffect, useState } from "react";
function App() {
let [userData, setUserData] = useState([{}]);
useEffect(() => {
const fetchUserData = async () => {
const response = await fetch(`http://localhost:5000/users`);
const data = await response.json();
setUserData(data);
};
fetchUserData();
}, []);
return (
<div>
<h1>Hello React World!</h1>
</div>
);
}
export default App;
Just don't use 'localhost'. Put everything as 127.0.0.1
Font: hours trying every solution possible.
From trying to replicate your issue I think in your proxy you have "proxy": "http://localhost:5000/", but then you also pass a fetch request for "/users" which would lead to a "http://localhost:5000//users.
I would imagine that when you were trying to figure this out that the issue was that you didn't restart your React App after changing the package.json to include the Proxy, and then by the time you restarted the React App, you had already added the extra "/".
Also in your browser console.log when, no matter where your proxy is it will come up with http://localhost:3000 as the address rather than your actual endpoint - it can be a bit of a red herring
Hope it helps
I finally got it to work!
After a lot of experimenting, I realized that this was indeed an environment problem. That explains a lot since the many other suggestions I tried worked for other people but not for me.
What had happened was that my client-side was using wsl for the terminal yet my backend was using PowerShell. When I switched both to wsl it worked. Or when I switched both to Powershell it also worked.
I am at early stages setting up a next.js application, I only had experience using react so far.
I setup docker with a frontend app (next.js) on localhost:3000 and a backend app (node.js/express) on localhost:5000. They both work.
Now I am trying to call an express endpoint from the frontend, what I am doing is:
const registerUser = async event => {
event.preventDefault()
const res = await fetch(
process.env.NEXT_PUBLIC_SERVER + '/user/signup',
{
body: JSON.stringify({
username: event.target.name.value,
email: event.target.email.value,
password: event.target.password.value
}),
headers: {
'Content-Type': 'application/json'
},
method: 'POST'
}
)
result = await res.json()
}
and I am getting an error saying
Access to fetch at 'http://localhost:5000/user/signup' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
just a note: the endpoint works as expected using Postman.
I made some research and I find a few resources saying I should call an internal next.js endpoint (pages/api), and from there call my api. Is this the best practice with next.js? In react I just use to call the api directly.
Other than just how to solve this, I would like to know what's the best practice in this case? Thanks.
If you have separate servers for frontend and backend (for example, next.js and express) that cannot listen on the same port, there are two broad alternatives:
Either the browser loads the frontend from one server and makes API requests to the other server
next.js <-- browser --> express
This requires the backend app to set CORS headers, for example, using cors and the statement
app.use(cors({origin: "host of next.js", ...}));
Or the browser makes all requests to the port of next.js, and this forwards all API requests to the other server
browser --> next.js --> express
No CORS is necessary in this case, but API requests take more hops than before. So it is simplicity vs performance (like so often).
First of all, are you sure you need an Express BE? The power of Next.js relies in its serverless approach, most of times, unless you have a very complex BE, you can do everything with serverless functions.
If you really need to have a separate express server for your Next application remember that you will lose some important Next features:
Before deciding to use a custom server, please keep in mind that it should only be used when the integrated router of Next.js can't meet your app requirements. A custom server will remove important performance optimizations, like serverless functions and Automatic Static Optimization.
Usually to address the CORS issues in dev environment, since you need FE to run on a different PORT from BE to have Hot Reload, when you use React the best approach is the proxy approach, you can just add an entry to package.json on the React project,
"proxy": "http://localhost:5000" (if your server runs on PORT 5000)
Source: https://create-react-app.dev/docs/proxying-api-requests-in-development/
This way all the http traffic is going to be redirected on port 5000 and will reach your Express server, while keeping having hot reload features and your client files running on port 3000.
By the way, that's the case if you have a standard React FE and a custom Express BE, if you are using NextJS even with a custom Express Server, you need to create the server and to connect it using Next:
/ server.js
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
// when using middleware `hostname` and `port` must be provided below
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer(async (req, res) => {
try {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
if (pathname === '/a') {
await app.render(req, res, '/a', query)
} else if (pathname === '/b') {
await app.render(req, res, '/b', query)
} else {
await handle(req, res, parsedUrl)
}
} catch (err) {
console.error('Error occurred handling', req.url, err)
res.statusCode = 500
res.end('internal server error')
}
}).listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://${hostname}:${port}`)
})
})
source: https://nextjs.org/docs/advanced-features/custom-server
Again, I suggest you to deeply evaluate if you really need a custom express server for your app, because most of times you don't, and development experience is much smoother in a serverless environment!
I'm trying to weather Api app using node, express and Axios in backend part without using any framework like Angular or react.
I have 3 main file for my codes.
index.html
customer.js (for front end part)
server.js (for backend part)
My backend part like below;
const express = require('express');
const app = express();
const axios = require('axios').default;
API_KEY = "***";
const PORT =3000;
// app.use("/static", express.static(__dirname + '/customer'));
app.get('/', (req, res) =>{
axios
.get(`http://api.openweathermap.org/data/2.5/forecast?q=amsterdam&appid=${API_KEY}`)
.then(resp => {
let weatherDetail = resp.data;
console.log('a single country details: ', weatherDetail);
res.send(weatherDetail);
})
.catch(err => console.log(err));
});
app.listen(PORT, () => console.log(`My app listening on port ${PORT}! `));
When I write localhost:3000 on browser, I can see the weather api's data. However I want to see html file with functions in customer.js and api's data. Therefore I tried to write res.sendFile((__dirname + '/index.html')); inside app.get('/', (req, res)) function. However, in this situation I can see only html page without getting data from backend.
How can I call data getting from backend part in frontend part inside customer.js file?
My codes in customer.js like below (but I'm not sure if I use axios agan inside this file)
const apiCall = cityName => {
let apiKey = "***";
let apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${apiKey}&units=metric`
axios
.get(apiUrl)
.then(getWeather)
.catch(err => {
console.log(err);
err.response.status === 404 ? alert(`The country ${cityName} doesn't exist.`) : alert('Server error! Sorry.');
});
};
apiCall(amsterdam)
function getWeather (response) {
let city = document.querySelector("#city");
city.innerHTML = response.data.name;
.
.
.
.
}
I would recommend to use a templating engine like handlebars or ejs.There are tons of examples for it, and sending data from backend to frontend becomes a piece of cake when using any templating engine. my personal favourite is handlebars because of its simple syntax.
It is advisable not to use document.querySelector if you're using Angular or React. React/Angular will have the browser repaint the DOM by making updates in the "root" div element of the index.html file whenever there is new data available to update.
Also, why do you want to send a HTML file? You could have a route in Node like below
route.get('/weather', (req, res) => {
// do your api call with axios to get weather data
res.json(weatherData);
});
from your front-end you could make an API call to '/weather' route and consume the JSON data
axios.get('baseUrl/weather').then(res=>{
console.log("weather data", res);
}).catch(...);
You could also fetch weather data directly from front-end like above.
Im trying to send a POST request from my React application. The application is running locally in node on localhost:8000.
I've tried running in locally on localhost:5000 and also pushed the server application to a heroku webaddress and tried sending to that address.
So basically my question is;
1. how do I send a POST request to my heroku server when i'm running my react application locally on localhost?
2. How do I receive this POST request on my heroku server/node application?
React code for sending POST request:
import React, { Component } from 'react'
import axios from 'axios'
require('styles/_webshopPage/webshop.css')
export default class Checkout extends Component {
postRequest() {
let nodeServerURL = 'https://peaceful-mountain-93404.herokuapp.com'
let reqData = {
msg: 'hello!',
}
// Send a POST request
axios({
method: 'post',
url: nodeServerURL,
data: reqData
})
}
render() {
return (
<div >
<button onClick={this.postRequest.bind(this)} type="button" name="button">Send req</button>
</div>
)
}
}
Code for my heroku server:
var express = require('express')
var app = express()
app.set('port', (process.env.PORT || 5000))
app.use(express.static(__dirname + '/public'))
app.post('/', function(request, response) {
response.send('Hello World!')
})
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
})
I have done something similiar like that..
I think Fetch api works perfectly with it .
Fetch provides a generic definition of Request and Response objects (and other things involved with network requests). This will allow them to be used wherever they are needed in the future, whether it’s for service workers, Cache API and other similar things that handle or modify requests and responses, or any kind of use case that might require you to generate your own responses programmatically.
I have typing some random example here, hope it will you to understand how fetch api exactly works
var data= "somerandom string";
fetch('http://localhost/react_task/form_send.php', {
method: 'post',
body: JSON.stringify({
Password: data,// this is posted on another server
})
}).then(function (res) {
return res.text();
}).then((body)=> {
console.log(body)// body can be used to get data from another server
});
i think fetch helps perfectly lot for posting and getting data from another server..
Enjoy Coding.