Can I create a local API? - reactjs

I'm learning about fetch and promises on reactjs, and sometimes I had a problem with my internet connection. So is it possible for me to create my own API but still can use or call it with fetch() function?

You could use mocking tools to mock the APIs.
One such example is https://mockoon.com/

You can setup a local server and use fetch() to pull from localhost.
This is an example Node server:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('test')
})
const server = app.listen(8081, () => {
console.log("Example app up")
})
You can then fetch() from localhost:8081

We can locally read the JSON data using fetch API in JavaScript. If you are using react hooks, place it inside the useEffect hook.
Check the console in this code sample link
Code: Your data.json will contain the sample JSON data.
fetch("./data.json")
.then(function (response) {
return response;
})
.then(function (data) {
return data.json();
})
.then(function (finalData) {
console.log(finalData);
})
.catch(function (err) {
console.log("Fetch problem show: " + err.message);
});

Related

How to retrieve Shopify's 'extensions' object in GraphQL response for query cost data

I have a React app that I have cloned from the shopify-app-node repo (the latest version using Express). I'm making GraphQL calls to Shopify's Admin API and I would like to also return cost information. I understand that there is an extensions object that contains this information but it is not returned in a typical GraphQL call. I have attempted to read and understand the documentation of Shopify/shopify-node-api but Shopify's current version of their React app doesn't reflect what the documentation states. Not in a way I can understand anyway.
This is the route defined when the server is initiated:
app.post("/graphql", verifyRequest(app), async (req, res) => {
try {
const response = await Shopify.Utils.graphqlProxy(req, res);
res.status(200).send(response.body);
} catch (error) {
res.status(500).send(error.message);
}
});
And then I make the query with the following: (apolloClient is being passed down from the parent component as this is a helper function and useQuery won't work due to it being a hook.
const apolloClient = useApolloClient();
apolloClient.query({
query: GqlProducts,
variables: {
count: 10
}
})
.then( response => {
console.log(response.data);
console.log(response.extensions);
})
.catch( error => console.log(error) )
Obviously I get an undefined on response.extensions.
Along with any hints or suggestions on how to get this working, I'm also curious to know why it's not returned in a typical response.

Combining a ExpressJS Router endpoint with a fetch call to an external enpoint

I am trying to create an Express Router endpoint that will return the CSV file from an external API (Jenkins in this case)
In more detail, what I am trying to achieve is to have a React Frontend call this route on the Express backend and download a CSV file.
BACKEND
The Express route is has this structure:
router.get('/path/latestCsvTestReport', async (req, res) => {
const { channel } = req.params;
return fetch(
`${jenkinsHost}/job/${channel}/${jenkinsPath}/lastSuccessfulBuild/artifact/test_result/report_test.csv`, {
...fetchOptions,
headers: { Authorization: jenkinsAuth},
},
)
.then(r => {
console.log('====== DATA =====', r);
res.setHeader('Content-type', 'text/csv');
res.setHeader('Cache-Control', 'no-cache');
res.send(r)
})
.catch((err) => {
// console.log(err);
res.status(404);
res.send('report not found');
});
});
and the URL called in the fetch returns a CSV file.
FRONTEND
I am calling the Express endpoint from a method on the React frontend using the following function, which utilised the file-saver library:
async function triggerReportDownload(chlId) {
console.log('===== CSV Request ====')
const resource = `/api/jenkins/${chlId}/latestCsvTestReport`;
saveAs(resource, "report.csv")
}
which is triggered by the click of a button on the FrontEnd.
At the moment, the button, triggers a download but the csv downloaded only contains:
{"size":0 timeout:0}
I am certain I am doing something completely wrong on the way the backend returns the CSV from the fetch call, but for the life of me I do not seem to be able to find the way to formulate the response. Any help/direction towards fixing this would be greatly appreciated.
The solution to this is to simply things as possible (being a newbie I had overcomplicated things). So here we are:
Backend
Import the utils library and then create a stream:
import util from 'util';
const streamPipeline = util.promisify(require('stream').pipeline);
This is then called from the Express router:
router.get('/jenkins/:channel/latestCsvTestReport.csv', async (req, res) => {
const { channel } = req.params;
const response = await fetch(
`${jenkinsHost}/job/${channel}/${jenkinsPath}/lastSuccessfulBuild/artifact/test_result/report_test.csv`, {
...fetchOptions,
headers: { Authorization: jenkinsAuth },
},
);
res.setHeader('Content-disposition', `attachment; filename=report_test_${Date.now()}.csv`);
res.set('Content-Type', 'text/csv');
return streamPipeline(response.body, res);
});
Frontend
Use windows.open to get the download file
async function triggerReportDownload(chlId) {
window.open(`/api/jenkins/${chlId}/latestCsvTestReport.csv`);
}

Why am I getting empty array in fetch request to MongoDB from ReactJS?

I am trying to fetch all the articles from a document in MongoDB in React. It is perfectly working in Backend with NodeJS when I tested with Postman. But in Frontend , React, I am getting empty array. How to solve this.
Server.js (Backend)
app.get('/api/articles', async (req, res)=>{
const client = await MongoClient.connect('mongodb://localhost:27017', {useNewUrlParser:true, useUnifiedTopology:true})
const db = client.db('my-blog')
const articleInfo= await db.collection('articles').find({}).toArray(function(err, result){
if (err) console.log(err)
res.status(200).send(result)
client.close()
})
})
articlePage.js (FrontEnd)
componentDidMount(){
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
};
const fetchdata = fetch('/api/articles/').then(res=>res.json())
.then(data=>this.setState({articles:data}))
console.log(this.state.articles)
}
Api address is set up in package.json with proxy:http://localhost:8000
How to get the documents data from MongoDB in React?
Firstly, check if you the API call went through to the server from your React app. If it has, then check for the response code in the network. In your case, 200 is where you get the desired result from the API. If you are not getting the desired result, then check your collection and document names and also arguments your are passing in the query.
As setState is not synchronized, you have to access it in the callback.
this.setState({ articles: data }, () => {
console.log(this.state.articles)
})

Cannot make a GET request in Postman with React

I created a joke generator app that takes jokes from a local json file with data that I created and displays it in the browser. This app has no backend at all. I am trying to make a GET request through Postman, but no luck. Is it even possible to use postman in this scenario?
NO Postman is not used for programmatic api calls. Use axios for this. Suppose your server is running on localhost:3000.
npm install axios
In your component,
const axios = require('axios');
// Make a request for a user with a given ID
axios.get('/jokes?id=1')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});

React won't respond to any request

I am working on an app where I am making a request and trying to send my data back to react via fetch.
So far here's my router file:
router.get('/', (req, res, next) => {
console.log('I got here before request..... >>>>>>>>>');
request(`https://rest.coinapi.io//v1/exchangerate/BTC?apikey=${API}`, (error, response, body) => {
console.log('I got here..... >>>>>>>>>');
if(error){
console.log('error >>>>>>', error);
}
console.log(response.body);
});
});
And i included to main server,js
// include routes
var routes = require('./routes/index');
app.use('/', routes);
app.listen(3000, () => {
console.log('Listening to port 3000...');
});
And then finally I sent my data to react:
class MainApp extends Component{
constructor(props){
super(props);
this.state = {
data: null
}
}
componentDidMount() {
this.getInitial();
}
getInitial() {
fetch('/')
.then(resp => resp.json())
.then(data => this.setState({
data: data.rates
}))
.then(() => console.log('this is is a state >>>>+++', this.state))
.catch(err => console.log(err))
}
render(){
return (
<div>
<h1>HELLO WORLD FROM REACT CLIENT FRONTEND! PP</h1>
<p>{this.state.data}</p>
</div>
);
}
}
For some reason I am not getting any console.log on my express when i run my code and I am getting this error: SyntaxError: Unexpected token < in JSON at position 0
Any idea what am doing wrong why I can't change the state? and why the request doesn't run?
The problem isn't React. The data is in JSON form, which has bunch of keys, value inside. You need to use a map function to render the {this.state.data}. You can not call a entire JSON object like that. You have to dig deep in the JSON Object and get whatever you need.
Let's assume you have the following JSON data.
{
"crypto": {
"BTC": {
"name": "bitcoin",
"current_price": "$6592.3"
}
}
}
you can't just say {this.state.data}. In this case you probably will do something like this {this.state.data.crypto.BTC.name} to get the name of the BTC-crypto symbol. Using the map function you can get name and prices of all the crypto symbol assuming there are more.
actually your code on server does not send any response. When you are using console.log on server - you will see that messages in terminal, where you execute command "nodejs app.js" or some other to start server. To send response, depending on node framework, you are using, you should do something like this:
router.get('/', (req, res, next) => {
...
res.setHeader('Content-Type', 'application/json');
res.send(SOME_JSON);
});
Also as i see, your server is listening port 3000, but fetch sends request not there

Resources