I am very new to React Native, Networking, and Programming as a whole. I am attempting to fetch JSON data from Reddit for an app I'm building, but I am receiving error messages when trying to access the Objects of the data. Below is the code I am using to fetch and console log this data.
componentDidMount(){
fetch ('https://www.reddit.com/r/financialindependence.json')
.then(res => res.json())
.then(data => {
this.setState({
data: data
})
})
.catch( error => {
console.error(error)
})
}
render() {
const myData = this.state.data
if (myData !== undefined) {
console.log(myData)
}
return(
<View style = {styles.container}>
<MainDrawerHeader title = 'Links' />
<Text> This is the Links Screen </Text>
</View>
)
}
}
This works and logs to the console the following.
[16:54:41] Object {
[16:54:41] "data": Object {
[16:54:41] "after": "t3_9ysab7",
[16:54:41] "before": null,
[16:54:41] "children": Array [
[16:54:41] Object {
[16:54:41] "data": Object {
[16:54:41] "approved_at_utc": null,
[16:54:41] "approved_by": null,
[16:54:41] "archived": true,
[16:54:41] "author": "Omitted For Privacy",
And when I access myData.data , it works as well
[16:59:29] Object {
[16:59:29] "after": "t3_9ysab7",
[16:59:29] "before": null,
[16:59:29] "children": Array [
[16:59:29] Object {
[16:59:29] "data": Object {
[16:59:29] "approved_at_utc": null,
But when I try to access the second nested object (either 'after', 'before', or 'children' (and since children is an array, I tried to access the first element) I receive the following error:
[17:00:39] TypeError: TypeError: TypeError:
undefined is not an object (evaluating 'myData.data.after')
Which confuses me because I tried to catch the undefined object with my 'if' statement. Any tips, not sure where to go from here. Thank you
I could be mistaken here, but in your third line it appears you may not be returning the res.json() to the next .then() in your Promise chain, like so:
componentDidMount(){
fetch ('https://www.reddit.com/r/financialindependence.json')
.then(res => {
let resultToPass = res.json();
return resultToPass;
})
.then(data => {
this.setState({
data: data
});
})
.catch( error => {
console.error(error)
})
}
At least superficially that would explain to me why you can access the res values and log them but they're not making it to your screen components -- they just aren't making it to where you're calling this.setState({data: data}).
Edit: I broke out the return statement by first assigning a variable, but I believe you could just as easily do return res.json(); and be fine.
Edit 2: Moved the second set of }) for the this.setState() because I made a formatting goof.
Related
Below is a dropdown which should ideally display a list of all tables belonging to a particular user.
<v-select
:items="allTables"
:item-text="tableNames"
return-object
/>
This is the structure of allTables. There could be more or less depending on the user:
[
{
"id": 3,
"name": "TABLE"
},
{
"id": 4,
"name": "KOP"
}
]
This is the method which displays tableNames:
tableNames() {
this.allTables.forEach(el => {
return element.map(a=>a.name)
});
},
Originally it was like this (however it led to the error I've listed in one of the answers):
tableNames: item => item.name;
Console logging
console.log(el.map(a=>a.name))
within the method above returns an array like below ('TABLE' is the name of a table and 'KOP' is the name of another table).
It's not returning any errors but the options for the v-select return [object Object]. I'm not sure what I'm doing wrong, can I ask why it's returning this?
The function to get all tables:
public function retrieveAllTables()
{
return Auth::user()->client->tables()->get();
}
Data variable:
data: () => ({
allTables: []
}),
API request:
getAllTables() {
apiClientGet(
routes["pages.retrieveAllTables"],
null,
response => {
this.allTables.push(response.data.flat());
// console logging this.allTables shows the structure above
}
);
},
The problem was that the api request wan't actually pushing the responses to allTables.
getAllTables() {
apiClientGet(
routes["pages.retrieveAllTables"],
null,
response => {
this.allTables = response.data;
return this.allTables;
}
);
},
I figured it out because console logging allTables in beforeMount returned an empty array when it should not have
My problem is that item stored in object (in an array of objects inside a state hook) is not being rendered on page, but it gets printed with console.log
I fetched some data from the server and it worked as expected, returning an array of two items, one of which is an object containing blog data(blog heading, creator, etc) an another is an array of 'sections' of that blog. Here is how I did it,
This is the initialization
// Get the blog id
const {blog_id} = useParams();
// Declaring our state hooks
const initial_blog_state = {
blog_id: blog_id,
heading: '',
creator: {},
created: '',
section: [],
}
const [blog_state, updateBlogState] = useState(initial_blog_state);
Here is the fetching of data from the server
useEffect(() => {
// Fetching data
Promise.all([
fetch(`http://127.0.0.1:8000/api/blog/${blog_id}`),
fetch(`http://127.0.0.1:8000/api/section/full/${blog_id}`)
]).then(responses => {
// Get a JSON object from each of the responses
return Promise.all(responses.map(response => {
return response.json()
}))
}).then(function (data) {
// Log the data to the console
console.log(data);
// Update state
updateBlogState({
...blog_state,
heading: data[0].heading,
creator: data[0].creator,
created: data[0].created,
section: data[1]
})
}).catch(function (error) {
// if there's an error, log it
console.log(error);
});
}, []);
I think the way I'm updating the section inside the hook can be a problem(although I'm not sure how), because I saw in a stackoverflow answer that objects must always be initialized (which I'm not doing when declaring an array of 'objects')
And here is the thing that needs to be rendered
return (
<div className="container">
<h1>{blog_state.heading}</h1>
<p className="text-small text-muted">{blog_state.creator.username}</p>
{blog_state.section.map(item => {
{console.log(item.paragraph)}
<p>{item.paragraph}</p>
})}
</div>
)
Here blog_state.heaing and blog_state.creator.username are being rendered as desired and also console.log(item.paragraph) prints the correct paragraph on the console window, but item.paragraph doesn't show anything on the page.
Nothing is being returned from your map.
i.e you need to add a return line before the <p>{item.paragraph}</p>
So:
{blog_state.section.map(item => {
console.log(item.paragraph)
return <p>{item.paragraph}</p>
})}
or as an inline return:
{blog_state.section.map(item => <p>{item.paragraph}</p>)}
I'm new to web development and I'm running into an issue I can't solve...
I'm using Vuejs, Express, MongoDB and Fetch API...
In my script I'm fetching data from my local server:
mounted() {
fetch("http://localhost:5000/api/" + this.$route.params.id)
.then((res) => res.json())
.then((data) => {
this.data = data
console.log(this.data.telegram.length)
})
.catch((err) => console.log(err.message))
}
console.log is working fine.
data is returned like that:
{ "_id": "6061ee831114fc4c211678e6", "path": "mypath", "telegram": [ { "date": "2021-03-21T22:00:00.708Z", "followers": 2188 }, { "date": "2021-03-22T18:40:04.751Z", "followers": 2195 } ], "__v": 0 }
Then data is stored as:
data() {
return {
data: []
}
}
First of all, I'm surprised by the format of my data. I believed it was going to appear as JavaScript Format, meaning without quotes (" ") on keys... I tried to JSON.parse the response but it returns an error like if it was already parsed. Is it normal ?
Also, in my template, I'm unable to access properties of this 'data'.
For example:
<p>{{data.telegram[0]}}</p>
or
<p>{{data.telegram.length}}</p>
is returning 'Uncaught (in promise) TypeError: Cannot read property '0' of undefined' and 'Uncaught (in promise) TypeError: Cannot read property 'length' of undefined'.
It seems there is something I have not quite understood...
Any help appreciated !
data.telegram is undefined until your mounted method get a response from the server. I suggest you to replace your template code with a computed property that check if your data has value:
<template>
<p>{{mydata}}</p>
<p>{{telegramLen}}</p>
</template>
<script>
export default {
computed: {
mydata() {
if (this.data != [])
return this.data.telegram[0]
return "No data"
},
telegramLen() {
if (this.data.length > 0)
return this.data.telegram.length
return 0
}
}
}
</script>
I fetched my response by hitting an API and pushed each element of the response(which is an array of objects) onto an array in the state i.e mydata
state={
mydata:[]
}
componentDidMount() {
const headers = {
"Content-Type": "application/json",
};
Axios.get("/getmeetings", {
headers
})
.then((res) => {
if (res.status === 200) {
console.log(res);
res.data.forEach((e, i) => {
this.state.mydata.push(e)
})
} else {
alert(res);
}
})
.catch((error) => console.log(error));
}
Now the problem is when I try to access the length of my state variable it gives it as 0
I tried printing the array and I can see that there are values available.
I also checked if my state variable was getting correctly populated using the chrome react extension.
Now another weird thing is when I hardcoded another object into the mydata variable
state= {
mydate = [{name:"temp"},{age:"1234"}]
}
and then again pushed my responses onto that array and later when I checked its length, it gives me 2. When I tried to print that array it shows those 2 objects plus my other pushed objects.
This is a sample object I'm trying to push
{
"agenda": "sadsadasd",
"project": "ECAM",
"meeting_title": "asdasd",
"meeting_id": "1588072890",
"attendees": [
"a##$$",
"a#a"
],
"date": "1588072890",
"host": "a#a"
}
Consider avoiding direct push since it will mutate the state. Use setState function instead.
this.setState(({ myData }) => ({ myData: [...myData, res.data] }));
I have a structure like this:
{
"RESTAPI": {
"uniqueId": {
"id": "1",
"data_2": "data_2",
"data_3": true,
"mg_gateway": "Another Object"
},
"uniqueId2": {
"id": "1",
"data_2": "data_2",
"data_3": true,
"mg_gateway": "Another Object"
}
}
}
uniqueId can be with letters and numbers. I try to get it:
componentDidMount() {
axios.get('https:LINKNAME/RESTAPI.json')
.then(res => {
const fetched = res.data;
this.setState({ data: fetched });
})
}
And show in JSX:
{Object.keys(this.state.data).map((obj, i) => {
return <p key={i}>{obj}</p>
})}
In browser I can see only strings (typeof string): uniqueId and uniqueId2
But in console log I get all Objects.
console.log
But I cant show data inside each nested Object in map. So I try to use obj.data_2 and got undefined.
I thought that I can create new obj.map inside, but obj always string so it's impossible. Please, help me
You could use Object.values instead of Object.keys, then obj will be:
{
"id": "1",
"data_2": "data_2",
"data_3": true,
"mg_gateway": "Another Object"
}
or you can do this.state.data[key] as in previous replies
{Object.keys(this.state.data).map((key, i) => {
return <p key={i}>{this.state.data[key]}</p>
})}
Object.keys gives you only keys of object that is why you are only seeing the keys(uniqueId,uniqueId2)
So if you want whole data along with uniqueId do
this.state.data.map(...your code);
But I suspect you might get something like [object] so use
JSON.stringify in map function.
Or you can simply replace
<p key={i}> {this.state.data[obj]}</p>