Using fetch data to post to API - node.js

I have fetch data I am trying to re-use this data to push to a DB that then triggers a stored procedure
I have tried reusing the variable on a new function and get undefined, I don't even know where to start if using the existing axios get.
getEFID = (e) => {
e.preventDefault();
const EFID = e.target.elements.EFID.value;
console.log(EFID);
axios.get(`/api/vWEFID/${EFID}`)
.then((res) => {
console.log(res);
const DAEFForm = res.data;
this.setState({
DAEFForm: res.data
})
console.log("Getting transport Information...", DAEFForm)
});
}
TransportEF = (e) => {
//const tEF =
this.setState({ show: false });
e.preventDefault();
const TransportEF = e.target.elements.getEFID.DAEFForm.data;
/*axios.get(`/api/tEFID/`)
.then((res) => {
console.log(res);
const TransportEF = res.data;
this.setState({
TransportEF: res.data
})*/
alert('Transporting EF!')
console.log(TransportEF);
// })
}
If I can get the data out of the getEFID to TransportEF or somehow use the existing getEFID to console log the data then I can uncomment the API thats already set to post the data to the DB.

If I understand the issue correctly, you want to use response data from the API call in getEFID function as a payload within the API call inside the TransportEF function.
Since you tagged React and I can see setState being called, and assuming this is properly bound in both cases, all you really need to reference that data within TransportEF is this.state.DAEFForm.
See: https://reactjs.org/docs/state-and-lifecycle.html

Related

axios.put is not working when sending query object

I was trying to send put request using axios to update information about a book in mongodb, the code is working fine when using postman but it is not working using axios.put used inside react component when submitting, while axios.delete is working fine. I think the problem is that sending the query object in that way is not the right way but I am not able to find the solution.
This is the function that handleSubmit,
the 'id' is the id of the book
'updates' is a state object that contains all the changes that should happen in the book data.
And the second function handleChange is the function that setupdates according to changes in the inputs
const handleSubmit = async (e) => {
e.preventDefault();
try {
const res = await axios.put("http://localhost:8000/book/edit/" + id, {
params: {
updates,
},
});
setNewBook(res.data)
} catch (err) {
console.log(err);
}
};
const handleChange = (e) => {
e.preventDefault();
const value = e.target.value;
setUpdates({
...updates,
[e.target.name]: value,
});
};
maybe you misunderstood the axios put method. as per the axios docs provided (https://github.com/axios/axios#axiosputurl-data-config) the correct structure is axios.put(url[, data[, config]])
The first parameter is URL
The second parameter is data (body request).
3rd parameter is config (you leave params in this parameter)
It should be like this
const res = await axios.put("http://localhost:8000/book/edit/" + id, null, {
params: {
updates,
},
});
I hope this can help you

How to return success on a Post API call to MongoDB in NodeJS

I'm new to fetching and posting data using an API, and I can't work out how to do something once my Post has been completed.
I have a function that calls the API with the Post data. I need to set the loading state to false once the Post has been completed. Everything works apart from that, the data gets sent to Mongo, I just need to turn off my loading spinner once it has completed.
How do I do this, please?
This is how I'm trying to do it:
const postData = async () => {
setLoading(true)
await axios.post('/api/addData',form)
.then(response => {
setLoading(false)
})
}
And this is the API bit:
import { connectToDatabase } from "util/mongodb"
export default async (req, res) => {
const { db } = await connectToDatabase()
await db
.collection("posts")
.insertOne(req.body);
}
There is two potential problem in your code, first you're not sending any data back to the front in your backend code. Usually you send back the id of the inserted element (It can be usefull to do some mutation in your front), you'll also need to try catch your call to the db to notify that something went wrong to the front end side :
import { connectToDatabase } from "util/mongodb"
export default async (req, res) => {
try {
const { db } = await connectToDatabase()
const insertedPost = await db
.collection("posts")
.insertOne(req.body);
res.status(201).send(insertedPost.insertedId);
// again it's up to you to know what can be usefull to your front-end to use
// Look at http status code online to know what's the best fit
} catch (err) {
res.status(500).send(err.message);
// send whatever that can be usefull for your front end to handle the error
}
}
In your front-end code you're using await with .then, it's weird usage. You can put your setLoading(false) after the await without the .then but you'll still need to try catch it. What I prefer to do is using the finally block to stop loading, so if my api call fail the loading is still stopped :
const postData = async () => {
setLoading(true)
try {
const response = await axios.post('/api/addData',form)
// do something with response
} catch (err) {
// notify user that something went wrong
} finally {
setLoading(false);
}
}
const postData = () => {
setLoading(true)
axios.post('/api/addData',form)
.then(response => {
// do something with response
})
.catch((err) => {
// notify user that something went wrong
})
.finally(() => {
setLoading(false);
})
}

How to use axios from react front end to get object from nodejs on component load (useEffect)

I have the following setup below and what i am trying to do is get allQuestions (an object) from nodejs backend and set its state to the questions state. console.log(data) shows my desired response but setQuestion(data) and console.log(question) returns an empty object. meaning set question hasnt worked. and my intention is to map through the question object after setting new state.
const Questions = (props) => {
const [question, setQuestion] = useState({});
useEffect(() => {
axios.get(`http://localhost:4000/questions`)
.then(res => {
const data = res.data.allQuestions;
console.log(data);
setQuestion(data);
console.log(question);
})
.catch(error => {
console.log(error);
});
},[]);
setQuestion is an async call, meaning that it won't update right away. Instead of doing console.log(question) right after setting the state, you should do this:
useEffect(() => {
console.log(question);
},[question]);
This useEffect will be run once question is actually changed.

How to returned poll data after each nodejs api call to reactjs component

I need to poll the data until the response.Status === 'UpdatesComplete'.
I have written this node js API function which basically polls the data -
const getResults = async (location) => {
try {
const response = await poll(location);
if (response.Status && response.Status === 'UpdatesComplete') {
return response;
}
return await getResults(location);
} catch (err) {
throw err;
}
};
app.get('/url', async (req, res) => {
try {
const results = await getResults(req.query);
res.json(formatData(results));
} catch (err) {
res.status(500).send(err);
console.error(err);
}
});
I am calling this API from ReactJS class component inside ComponentDidMount lifecycle method -
componentDidMount = () => {
axios.get('url', {
params: params
})
.then(response => {
console.log(response.data, 'data');
// setting the data on state
this.setState({ filteredList: response.data });
})
.catch(err => {
this.setState({ error: true });
});
};
This is working fine. But since the API is returning data till all the data has been fetched(after doing polling), it's taking a very long time on view to load the data. I am basically looking for returning the polling data to view as soon as the data fetched and simultaneously polling the API until all the data has been fetched. In this case, data will keep on updating after each polling on the view which will improve the user experience.
Thanks in advance.
You are finding the lazy loading or infinite scroll solution on the server-side. There is no simple way to do this.
The basic idea of the solution is to paginate your result with polling. ie.
call url?size=2&offset=0 from the client-side. Then on the server-side just poll first 2 results and return. next time call url?size=2&offset=2 and so-on.

TypeError: firestoreService.snapshot_ is not a function

I've been using firebase functions test to do some testing on my functions. I have some code that is supposed to post a thing to firestore, basically in the same way that the examples show to do in the realtime database examples:
exports.addMessage = functions.https.onRequest((req, res) => {
const original = req.query.text;
admin.firestore()
.collection('messages')
.add({ original })
.then(documentReference => res.send(documentReference))
.catch(error => res.send(error));
});
For my test, I've spoofed some basic functionality using sinon, mocha and chai. Here is my current test, which is failing with the error message: TypeError: firestoreService.snapshot_ is not a function
describe('addMessage', () => {
// add message should add a message to the database
let oldDatabase;
before(() => {
// Save the old database method so it can be restored after the test.
oldDatabase = admin.firestore;
});
after(() => {
// Restoring admin.database() to the original method.
admin.firestore = oldDatabase;
});
it('should return the correct data', (done) => {
// create stubs
const refStub = sinon.stub();
// create a fake request object
const req = {
query : {
text: 'fly you fools!'
}
};
const snap = test.firestore.makeDocumentSnapshot({ original: req.query.text }, 'messages/1234');
// create a fake document reference
const fakeDocRef = snap._ref;
// create a fake response object
const res = {
send: returnedDocRef => {
// test the result
assert.equal(returnedDocRef, fakeDocRef);
done();
}
};
// spoof firestore
const adminStub = sinon.stub(admin, 'firestore').get(() => () => {
return {
collection: () => {
return {
add: (data) => {
const secondSnap = test.firestore.makeDocumentSnapshot(data, 'messages/1234');
const anotherFakeDocRef = secondSnap._ref;
return Promise.resolve(anotherFakeDocRef);
}
}
}
}
});
// call the function to execute the test above
myFunctions.addMessage(req, res);
});
});
My question is how the heck do I fix this?
I previously had a test that was just passing the first snap and fakeDocRef, and my test was passing fine, but as soon as I resolve the promise with the new fake document reference, it fails...
Any help would be appreciated! Thanks!
There are three different types of the calls, that are different:
Operating on the Collections.
Operating on the Documents.
Operating on the results of the query.
They have to be used consistently.
Please refer a documentation to see the difference operation on the collection and the document.

Resources