Undefined is not an object while trying to query nested objects. Using axios and React - javascript

The JSON response is as shown in the image 1.
I was able to assign the entire response using axios (which already does the JSON.parse) to the state (named profile).
while profile.bio and profile.image are working;
profile.user.username, etc are not working and throwing an error - Undefined is not an object
const [profile, setProfile] = useState({});
const phone_no = phone.phone;
const fetchProfile = useEffect(() => {
var res = {};
axios
.get('<API URL>' + phone_no)
.then((response) => (res = response.data))
.then(() => {
setProfile(res);
})
.then(() => console.log(profile))
.catch((e) => console.log(e)); });
const user_stream = {
name: first.first_name,
image: profile.image,
id: profile.user.id,
};
Update - Solution: Using async-await with axios, it's fixed.

profile or profile.user may still be undefined when trying to access it, so profile.bio is just undefined so it doesn't cause an error, but profile.user.username tries to access a property of an undefined object.
Try adding profile?.user?.username
Or profile && profile.user && profile.user.username
This will ensure that it only tries to render the username if profile is already defined

Related

TypeError: Cannot read properties of undefined (reading 'map') in NextJS - getStaticPaths

I have a problem with dynamic routing in next 13, I have dynamic page [id].js and trying to fetch the data
const res = await fetch(`myAPI`);
const resData = await res.json();
const paths = resData.data.map((r) => ({
params: { id: r.id}
}));
return {
paths,
fallback: false
}
It does not work and gives me error with .map function, if I hard code the path it works without any issue and give me correct output data
Hard coded example:
paths: [
{params: { id: '67'}}
],
I know that my map function should be correct as I tested in inside the component
axios
.get(`myAPI`)
.then((response) => {
console.log(response.data.map((res) => {return(res.id)}))
})
console output in component return data without complaining, why I cannot achieve it in getStaticPath?
resData is already your array of objects, so you can "skip" data:
const res = await fetch(`myAPI`);
const resData = await res.json();
const paths = resData.map((r) => ({
params: { id: r.id}
}));
The reason why when using Axios you have to use data, is because Axios already gets the response data as JSON for you (as data). You were confusing Axios' response for resData.

Uncaught TypeError: Cannot read properties of undefined (reading 'question'). This is after using useState() to set the data from a GET request

I am making a simple GET request and want to make that data more accessible using useState() but it seems as though this error is caused by accessing an property that does not exist due to useState not updating it?
Even though I have made GET requests very similar to this, it is the first time I am using useLocation(). I'm not sure if that has anything to do with the problem or it has something to do with useState().
Any response is much appreciated
const getQuiz = async () => {
try{
// These values were passed by the difficulty Component
const categoryName = location.state?.name
const difficulty = location.state?.difficulty
// This makes a get request to get data for the quiz
let response = await axios.get(`https://the-trivia-api.com/api/questions?categories=${categoryName}&limit=10&difficulty=${difficulty}`)
let arrayDataResponse = await response.data
// This sets the data to question array so that it is accessible outside of this function
setQuestionArray(arrayDataResponse)
// this outputs an empty array
console.log(questionArray)
} catch(err){
console.log(err)
}
}
// This fetches the data on mount
useEffect(() => { getQuiz() }, [])
// This will set the data for the elements once the state of the question array has been set from the get request
useEffect(() => {
// This sets the content for the question element
setQuestion(questionArray[0].question)
// <h4>{question}</h4>
// Uncaught TypeError: Cannot read properties of undefined (reading 'question')
}, [questionArray])
I'm guessing that your state is defined something like this...
const [questionArray, setQuestionArray] = useState([]);
const [question, setQuestion] = useState(/* some initial value */);
This means that when your component is initialised and mounted, questionArray is an empty array.
Effect hooks not only execute when their dependencies change but also when they are initialised. That means when this hook first runs...
useEffect(() => {
setQuestion(questionArray[0].question);
}, [questionArray]);
It's trying to access .question on undefined, hence your error.
I would skip the question state and the above hook entirely. If you want something to represent the optional first question, you can use a memo hook instead
const firstQuestion = useMemo(() => questionArray[0]?.question, [questionArray]);
or simply use questionArray[0]?.question directly without any hooks.
This will either return the first question property or undefined which you can detect using conditional rendering
{firstQuestion && (
<p>{firstQuestion}</p>
)}
{/* or */}
{questionArray.length > 0 && (
<p>{questionArray[0].question}</p>
)}
const getQuiz = async () => {
try{
// These values were passed by the difficulty Component
const categoryName = location.state?.name
const difficulty = location.state?.difficulty
// This makes a get request to get data for the quiz
let response = await axios.get(`https://the-trivia-api.com/api/questions?categories=${categoryName}&limit=10&difficulty=${difficulty}`)
let arrayDataResponse = await response.data
// This sets the data to question array so that it is accessible outside of this function
setQuestionArray(arrayDataResponse)
//Solution
// set question from here
setQuestion(arrayDataResponse[0].question)
// this outputs an empty array
console.log(questionArray)
} catch(err){
console.log(err)
}
}
// then you don't need to run useEffect for this , Your state will be fiilled with api response
// not required code below
useEffect(() => {
// This sets the content for the question element
setQuestion(questionArray[0].question)
// <h4>{question}</h4>
// Uncaught TypeError: Cannot read properties of undefined (reading 'question')
}, [questionArray])

getDocs - firebase react native

I want to get a document and to update.
I tried used this code, but he dont accept the "idDoc":
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
const idDoc = doc.id
})
})
.then(
updateDoc(doc(database, "user_veic", idDoc), {
kmF: "teste1",
km: "teste1",
}))
^^^^: FirebaseError: Invalid document reference. Document references must have an even number of segments, but user_veic has 1
I tried this:
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
const idDoc = doc(database, "user_veic", doc.id)
updateDoc(idDoc, {
kmF: "teste1",
km: "teste1",
})
})
})
^^^^: [Unhandled promise rejection: TypeError: doc is not a function. (In 'doc(database, "user_veic", doc.id)', 'doc' is an instance of lh)]
What did i do wrong?
In your first code example, you declare const idDoc inside of the callback parameter to .forEach(). That variable does not exist outside of the callback function. You then try to use it in the updateDoc() in a completely different block of code. It is undefined at that point, thus you are getting an error that you aren't passing enough parameters.
In your second code example, which is much closer to what you want to do, based on the error message it looks like you aren't importing doc with the rest of the Firestore functions from firebase/firestore.
RESOLVIDO #Greg thank you
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
let values = null;
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
values = doc.id;
});
var transactionUpdate = database.collection("user_veic").doc(values);
transactionUpdate.update({
kmF: kmF,
})
})

JavaScript Google Cloud Function: write Stripe values to Firebase

I'm new to JavaScript and I have written the following JS Google Cloud Function with the help of various resources.
This function handles a Stripe invoice.payment_succeeded event and instead of writing the entire data I am trying to save just both the sent period_start and period_end values back to the correct location in my Firebase DB (see structure below).
How can I write these two values in the same function call?
exports.reocurringPaymentWebhook = functions.https.onRequest((req, res) => {
const hook = req.body.type;
const data = req.body.data.object;
const status = req.body.data.object.status;
const customer = req.body.data.object.customer;
const period_start = req.body.data.object.period_start;
const period_end = req.body.data.object.period_end;
console.log('customer', customer);
console.log('hook:', hook);
console.log('status', status);
console.log('data:', data);
console.log('period_start:', period_start);
console.log('period_end:', period_end);
return admin.database().ref(`/stripe_ids/${customer}`).once('value').then(snapshot => snapshot.val()).then((userId) => {
const ref = admin.database().ref(`/stripe_customers/${userId}/subscription/response`)
return ref.set(data);
})
.then(() => res.status(200).send(`(200 OK) - successfully handled ${hook}`))
.catch((error) => {
// We want to capture errors and render them in a user-friendly way, while
// still logging an exception with StackDriver
return snap.ref.child('error').set(userFacingMessage(error));
})
.then((error) => {
return reportError(error, {user: context.params.userId});
});
});//End
HTTP type functions are terminated immediately after the response is sent. In your code, you're sending the response, then attempting to do more work after that. You will have to do all the work before the response is sent, otherwise it may get cut off.
If you just want to save the period_start and period_end values, instead of the entire data object, you can use the update() method (see https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields).
You should then modify your code as follows. (Just note that it is not clear from where you receive the userId value, since you don't show the stripe_ids database node in your question. I make the assumption that it is the value at /stripe_ids/${customer}. You may adapt that.)
exports.reocurringPaymentWebhook = functions.https.onRequest((req, res) => {
const hook = req.body.type;
const data = req.body.data.object;
const status = req.body.data.object.status;
const customer = req.body.data.object.customer;
const period_start = req.body.data.object.period_start;
const period_end = req.body.data.object.period_end;
admin.database().ref(`/stripe_ids/${customer}`).once('value')
.then(snapshot => {
const userId = snapshot.val();
let updates = {};
updates[`/stripe_customers/${userId}/subscription/response/period_start`] = period_start;
updates[`/stripe_customers/${userId}/subscription/response/period_end`] = period_end;
return admin.database().ref().update(updates);
})
.then(() => res.status(200).send(`(200 OK) - successfully handled ${hook}`))
.catch((error) => {...});
});

Unable to use external API on Botpress (axios)

When trying to use axis to query an external Weather API, I get this error
ReferenceError: axios is not defined
at getTropicalCyclones (vm.js:16:9)
Here is my action for getTropicalCyclones {}
(of course I have to hide my client ID and secret)
const getTropicalCyclones = async () => {
const BASE_WEATHER_API = `https://api.aerisapi.com/tropicalcyclones/`
const CLIENT_ID_SECRET = `SECRET`
const BASIN = `currentbasin=wp`
const PLACE = `p=25,115,5,135` // rough coords for PH area of responsibility
const ACTION = `within` // within, closest, search, affects or ''
try {
let text = ''
let response = {}
await axios.get(
`${BASE_WEATHER_API}${ACTION}?${CLIENT_ID_SECRET}&${BASIN}&${PLACE}`
)
.then((resp) => {]
response = resp
text = 'Success retrieving weather!'
})
.catch((error) => {
console.log('!! error', error)
})
const payload = await bp.cms.renderElement(
'builtin_text',
{
text,
},
event.channel
)
await bp.events.replyToEvent(event, payload)
} catch (e) {
// Failed to fetch, this is where ReferenceError: axios is not defined comes from
console.log('!! Error while trying to fetch weather info', e)
const payload = await bp.cms.renderElement(
'builtin_text',
{
text: 'Error while trying to fetch weather info.',
},
event.channel
)
await bp.events.replyToEvent(event, payload)
}
}
return getTropicalCyclones()
So my question is, how do I import axios? I've tried
const axios = require('axios')
or
import axios from 'axios';
but this causes a different error:
Error processing "getTropicalCyclones {}"
Err: An error occurred while executing the action "getTropicalCyclones"
Looking at the package.json on GitHub, it looks like axios is already installed
https://github.com/botpress/botpress/blob/master/package.json
However, I cannot locate this package.json on my bot directory...
Secondly, based on an old version doc it looks like this example code just used axios straight
https://botpress.io/docs/10.31/recipes/apis/
How do I use axios on Botpress?
Any leads would be appreciated
Botpress: v11.0.0
Simply use ES6 import.
include this line at the top of your code.
import axios from 'axios';
Note: I'm expecting that the axios is already installed

Categories

Resources