Adding variables to response data call in javascript - javascript

Is it possible to concatenate variable to a call to response data like so:
res.data.{some_variable}?
I am using axios to call an api, I get a JSON response and in order to get some specific info I have to call each key of the object. The keys are all numbered, "object_1", "object_2", "object_3" and so on. Right now I currently have to call it as many times as the keys are, but I'm wondering if there is a better way to do it.
I have tried res.data.object_${nr} but that didn't work.
This is my code:
const path= "path_to_api";
const object_nr = this.$route.params.nodeID;
axios.get(path)
.then((res) => {
this.object_devices = res.data.object_1;
})
.catch((error) => {
console.error(error);
});
But I would like to be able to add the object_nr like so: res.data.object_{object_nr}

You can get property using index syntax:
object['name']
So you can build your own index:
const foo = 'bar';
object[`name_${foo}`]

Related

Filtering objects after API call

I am having trouble showing the results after filtering the data received form API call, my guess is it is trying to filter the data before it has received it, and that is why it isn't showing. I have only managed to get the data by setting filterAnswers() to setTimeout function, but it loops continuously until it breaks. any idea how I can filter only the correct_answers and save it to state?
const [quiz, setQuiz] = React.useState([])
const [correctAnswers, setCorrectAnswers] = React.useState(filterAnswers())
React.useEffect(() => {
fetch("https://opentdb.com/api.php?amount=5&difficulty=medium&type=multiple")
.then(res => res.json())
.then(data => setQuiz(data.results))
}, [])
console.log(quiz)
function filterAnswers() {
let filter = []
quiz.forEach((question) => {
filter.push(decode(question.correct_answer));
})
return filter
console.log(correctAnswers)
};
my guess is it is trying to filter the data before it has received it
Indeed, the code is explicitly doing exactly that:
const [correctAnswers, setCorrectAnswers] = React.useState(filterAnswers())
You could invoke your "filter" logic when receiving the data, instead of immediately upon loading the component. First, change the function to no longer depend on state:
function filterAnswers(questions) {
let filter = [];
questions.forEach((question) => {
filter.push(decode(question.correct_answer));
})
return filter;
};
Then invoke it when you receive your data:
fetch("https://opentdb.com/api.php?amount=5&difficulty=medium&type=multiple")
.then(res => res.json())
.then(data => {
setQuiz(data.results);
setCorrectAnswers(filterAnswers(data.results));
})
Then of course the default initial state for correctAnswers would just be an empty array, exactly like it is for quiz:
const [correctAnswers, setCorrectAnswers] = React.useState([])
As an aside, it's worth noting that you're somewhat duplicating state here. Unless this filter/decode process is very expensive, it might be better to do this directly when calculating or display data rather than store it as state. Since this "correct answers" data is derived from the "quiz" data, by keeping both in state separately you also will need to keep that data synchronized. Changes to one need to be made in the other.
That might not become a problem with the functionality you're currently building, but it's something to keep in mind.

Update and increment value with realtime database

Im trying to update the points of the child : add 40points to the old result points, but I get the error :
undefined is not an object (Evaluating 'pointRef.update')
const pointRef=firebase.database().ref("Users").child(firebase.auth().currentUser.uid)
.once("value",(snapshot=>
{
pointRef.update({Points:snapshot.val().Points+40
})
You are using .once() method on pointRef so it is no longer a DatabaseReference. It is a DataSnapshot now. So you cannot call the .update() method on it. Instead try using the following code:
const pointRef = firebase.database().ref("Users").child(firebase.auth().currentUser.uid)
pointRef.once("value").then((snapshot) => {
pointRef.update({Points:snapshot.val().Points+40}).then(() => {
console.log("Points updated")
})
})
The better way of doing this:
firebase.database().ref("Users").child(firebase.auth().currentUser.uid)
.set({Points: firebase.database.ServerValue.increment(40)})
Here you don't need to manually fetch, add and update the points field.

Cloud functions error: Converting circular structure to JSON

Trying to use the admin SDK from Firebase to set custom claims within Firebase Cloud Functions. The issue seems to be the claims object I pass into the function. I understand what a circular object structure is, but I'm not sure why it is happening here.
The Error:
Here is the cloud function code
exports.setCustomClaims2 = functions.https.onCall((uid, claims) => {
return admin.auth().setCustomUserClaims(uid,claims).then(() => {
return {
message: `Success! User updated with claims`
}
})
.catch(err => {
return err;
})
});
And here is the front end code to call it:
let uid = "iNj5qkasMdYt43d1pnoEAIewWWC3";
let claims = {admin: true};
const setCustomClaims = firebase.functions().httpsCallable('setCustomClaims2');
setCustomClaims(uid,claims)
What is interesting is that when I replace the claims parameter directly in the cloud function call like so
admin.auth().setCustomUserClaims(uid,{admin: true})
This seems to work just fine.
Is there a difference in how the object gets received as a parameter?
You're not using the callable type function correctly. As you can see from the documentation, the function you pass to the SDK always receives two arguments, data and context, no matter what you pass from the app. A single object you pass from the app becomes the single data parameter. You can't pass multiple parameters, and that parameter doesn't get broken up into multiple parameters.
What you should do instead is combine uid and claims into a single object, and pass it:
setCustomClaims({ uid, claims })
Then receive it as a single parameter in the function:
exports.setCustomClaims2 = functions.https.onCall((data, context) => {
// data here is the single object you passed from the client
const { uid, claims } = data;
})
I'll note that using console.log in the function will help you debug what your function is doing. If you logged the values of uid and claims, this probably would have been easier to figure out.

Javascript saying object value is undefined. What am I doing wrong?

I'm trying to display the value of an object within an array of Github repositories (retrieved from a parsed JSON) in my React app but I'm getting an error that the browser can't read property key of undefined.
I'm able to console.log the JSON data and the objects within it but if I try to log the values within those objects, I get the error.
const App = () => {
const [repoList, setRepoList] = useState({});
useEffect(() => {
fetch("https://example.com/api")
.then(res => res.json())
.then(data => setRepoList(data));
});
return (
<div>{repoList[0].id}</div>
)
}
If I put JSON.stringify(repoList) within the div element, it shows the data.
If I put JSON.stringify(repoList[0]) within the div element, it also shows the data.
But if I put something like repoList[0].id nothing appears. This happens with each key listed. And I can confirm that the key is there. What am I doing wrong?
Try this.
const [repoList, setRepoList] = useState([]); // Change to array not object.
...
return repoList.length ?
(<React.Fragment>{repoList[0].id}</React.Fragment>)
: (<span>Loading ....</span>)
If your div does not have styles, better user Fragment, it result in better performance.
You're calling async functions to populate the repo list. The first time the return tries to use repoList[0].id, there is no repoList[0]. You may want to initialize repoList to a non-error-ing dummy object when you set it up with useState({})

Reading data after writing to it in Firebase

I am trying to navigate to a specific ID after creating an item in my realtime database.
The documentation offers a solution but it is not working as shown.
After using the push().set() method on my db ref I tried creating a callback function that would get the specific ID created using the push.().set() method and then navigate with that ID.
db.ref.push().set({
...
}).then(function(){
router.navigate(ref/ + db.ref.key /)
})
After creating a new object at that ref point I want to use the ID created by firebase to navigate to a specific route using that ID.
The issue is that db.ref.push() returns a new Reference object with the unique id to it. You're not getting the value of that ID. You can refactor things so it would be something like:
let newref = db.ref.push();
newref.set({
...
})
.then( () => {
// You can use "newref" here
// The last part of the full reference path is in "key"
let id = newref.key;
// Do something with the id as part of your route
});
set
set(value, onComplete) => returns firebase.Promise containing void
So you are absolutely correct about that you should be able to see the operation as resolved with a callback however the promise will not give you any key back.
You should however be able to chain this event:
db.ref.push().set({
...
}).getKey().then(data => console.log(data))

Categories

Resources