I am a university student and this is my first time of putting all together of server, api and client sides.
My problem is that first I have created an API using Django-Rest framework.
When I post data to that server using fetch function in JavaScript, it keeps posting that data and does not stop until I close. In the server database, many same data have been created.
I cannot figure out how to fix it. My intention was I want to post the data just once.
Please help me how to do it.
Thank you.
This is my javascript code ๐
const testPost = () => {
fetch('http://127.0.0.1:8000/mysite/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'player1Hp': 30,
'player2Hp': 20
})
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
.catch(error => console.log('ERROR'))
}
This is views.py in Django ๐
views.py photo
This is many POST messages in terminal cause of infinite looping ๐terminal photo
This is full screenshoot of script.js ๐ script.js photo
HTML just calls script and the rest is just blank. ๐ index.html photo
Related
The useEffect() is responsible for displaying all data (it gets an array). When the user navigates to the page, all photos will be displayed automatically.
Once the user uploads successfully and you refresh the page, the uploaded photo correctly appears on the bottom along with the other already uploaded photos above it.
However, I'd like the newly uploaded photo to appear at the top instead of the bottom upon the user uploading data.
In other words, move it to element to the front of the array so that when the user refreshes, the data appears on top and not on the bottom.
I know unshift() should be used to achieve this but I've tried many ways in the fileUpload() function but to no avail. How can I achieve this? Should this even be handled on the client side or server?
useEffect(() => {
const headers = {
"Accept": 'application/json',
"Authorization": `Bearer ${authToken}`
};
axios.get('http://127.0.0.1:8000/api/get-user-uploads-data', {headers})
.then(resp => {
setGridData(resp.data);
}).catch(err => {
console.log(err);
});
}, []);
const fileUpload = () => {
const url = 'http://127.0.0.1:8000/api/file-upload';
let formData = new FormData();
let imagefile = document.querySelector('#file');
formData.append("image", imagefile.files[0]);
const headers = {
"Accept": 'application/json',
"Authorization": `Bearer ${authToken}`
}
axios.post(url, formData, {headers})
.then(resp => {
let first = localStorage.getItem('UserID') === gridData[0]['UserID'];
gridData.unshift(first);
}).catch(error => {
console.log(error);
});
};
If you're refreshing the page, your component is reloading and your API call inside useEffect is getting the fresh copy of the data from the server side again.
If you really want your data to be displayed in the latest upload first order, you could sort them with timestamps(if you have that information available) or get this data sorted already from the server side.
Keep in mind that if you have a long list and plan to paginate it, it's better to do it on the server side otherwise on each fetch the sorting on the frontend side will not look very good because of some other items shifting randomly.
I don't have much experience with React or JavaScript. I am creating a simple application that fetches time series data from an API. The data is used to plot a line chart (React Apex Chart). All good.
The problem is that the API response size is limited to a maximum of 2,000 records, and sometimes we need more data.
The API documentation says:
The response size is limited to a maximum of 2,000 records. If more records have to be returned, the response header contains a Link header with a URI to get the next set of records:
Link: https://apiurl; rel="next"
My Fetch Code:
My code fetches the api data, sorts it and sends it to the child component(Chart).
FetchAPI(){
fetch(https://MYURLHERE?from=FROMDATE&to=TODATE)
.then(response => response.json())
.then(data => this.setState({
kWhData: data.map((kWh) => kWh._kWh),
TimeStampData: data.map((time) => time._time),
loading: false
}))
.catch(error => console.log('Fetching failed', error))
}
Link header: linkย โ<https://MYURLHERE?from=FROMDATE&limit=2000&to=TODATE>; rel="next">
I know the solution may be some kind of pagination but I do not fully understand this concept. I have searched for similar problems with no luck.
Hope someone could provide me with a helping hand, tips or code.
I don't know what API you're using, but it sounds like all you need to do is get the URL to the next set of results from the headers and then make a request to that.
Before you return response.json(), you can access the headers with response.headers.get(). So you can do something like let nextPage = response.headers.get('Link') to get that full Link header as a string. Then you can split it at the semicolon and use the first part as the URL for the next paginated request.
If I've understood the question correctly, I would add a variable to your FetchApi function, so that it can query either your initial API URL, or the URL for a subsequent page:
FetchAPI(requestURL){
// Fetch function here
}
The idea is that this function can then call itself iteratively, with the url of the โnextโ page of results passed as a parameter for each call, until the response indicates all the data has been retrieved.
So your initial call would be FetchAPI('https://MYURLHERE?from=FROMDATE&to=TODATE').
You can then add a line to call this function again if the rate limit is reached. E.g:
FetchAPI(requestURL){
fetch(requestURL)
.then(response => {
if(response.dataLimit == true){ // Or however this is expressed
// Concat new data with any already retrieved
this.FetchAPI(nextPageUrl) // Get the URL of the next page and call FetchAPI again with this e.g https://MYURLHERE?from=FROMDATE&limit=2000&to=TODATE
} else {
// Otherwise stop and do something else now that you have a complete set of data
}
})
}
Worth saying that this is untested code, but hopefully enough to get the principle across.
Also if the API has a request rate limit e.g. 1 second, you could add a delay before the function calls itself again, though obviously this will impact the overall time to retrieve all of the data.
Thank you all. I got it to work with a mix of both answers.
I do not know if this is a good way to do it or the "right" approach. Maybe you guys could give me some feedback?
The setTimeout was just for testing, but I think I need to have minimum 1000?
The credentials/header is necessary to get the API.
FetchAPI(requestURL) {
fetch(requestURL, {
credentials: 'include',
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"x-xsrf-token": this.myXRSFToken,
"origin": `${window.location.protocol}//${window.location.host}`
}
})
.then(response => {
let Responseheader = response.headers.get('Link')
response.json()
.then(data => this.setState({
TestData: this.state.TestData.concat(data)
}))
if (Responseheader){
let nextPageUrl = Responseheader.match(/\bhttps?:\/\/\S+Z/gi)
setTimeout(() => {
this.FetchAPI(nextPageUrl)
}, 2000);
} else {
console.log('Done fetching API')
this.setState({
loading: false
})
return
}
})
.catch(error => console.log('Fetching failed', error))
}
I am using Nodejs, Express, MySQL, body-parser and EJS.
What I am trying to do is, when someone press on a button, it sends a PUT request which will update the counter by 1, I am trying to send the ID of the pressed button so it can be incremented by 1.
app.put("/toolong", function(req,res){
console.log(res.status(200).json({voteNum: 5}))
}
)
The Fetch:
function upvote(click){
// when the upvote button is clicked
let idOfClicked;
console.log(event.target.attributes[1].value)
idOfClicked = event.target.attributes[1].value
fetch(`/toolong`, { method: 'PUT', data: {id:9} })
.then(res => res.json())
.then(jsonRes => {
console.log(jsonRes.voteNum) // gives 5
})
}
I am trying to send the variable idOfClicked from the Fetch to my app.put so I can do a SQL query which will use that variable.
I assume you are able to do it, the "data" key in the fetch is something I tried from seeing some examples but I wasn't able to send it through
It's a body key instead of data.
I fixed it, the problem was I didn't have "headers: new Headers({ "Content-Type": "application/json" })" in my app.put, I placed it after my "body"
I'm using node.js/express, and I've got a view with a form on it - that form POST's to a route, which then returns json.
I'd like to (to start with at least) send off my form, and have the data that's returned be shown underneath the form (on the same view).
What's the best way of doing this in the most 'express-y' way possible?
Ideally without a page refresh.
Ajax will do what I'm after - but is that a great way of doing it?
Thanks for any insight
The bare minimum of what you're looking for would look something like this:
Client side
fetch('your_endpoint', {
method: 'POST',
body: JSON.stringify(formData),
}).then((response) => {
// success
return response.json();
})
.then((data) => {
// add data to DOM
})
.catch((error) => {
// failed to send
});
}
Server side using Expressjs
router.post('/your_endpoint', (req, res, next) => {
// process request
res.status(200).json({ "data": your_data });
});
I'm working on something where I need to poll an http URL and get the numbers available as part of the response and show graphical stats on a web page.
Does anyone know of any opensource software which can do something like this?
Sample URL:
http://dataqueue.com:8080/datamq/message/getcount?q=order.sales&class=com.xyz.entitiy.Order&metadata={}
which Results 15000
then another url would result 10000 etc.
If I understand your question correctly, you can use plain Javascript to achieve something like this. Here's an example that does a server request every five seconds:
function req() {
fetch('http://reqres.in/api/users', {
method: 'post',
body: JSON.stringify({
name: 'morpheus',
job: 'leader'
})})
.then(res => res.json())
.then(json => {
document.getElementById('View').innerHTML = json.id;
});
}
req();
setInterval(() => req(), 5000);
<div id="View"></div>
There are also libraries that make this easier, for example PollJS. You can find more on Github. If you have control over the server, you might want to check out Socket.io.