Not able to access elements from an array of objects - javascript

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] }));

Related

Delete record from an array of objects in javascript

I have an array of objects that I get from an api, I get the data but I want to remove the ones that have a finish status after x time.
First I must show all the records, after a certain time the records with FINISH status must be deleted
I am using vue.
This is the response I get:
[
{
"id": "289976",
"status": "FINISH"
},
{
"id": "302635",
"status": "PROGRESS"
},
{
"id": "33232",
"status": "PROGRESS"
}
]
This is the method that obtains the information:
I use setTimeout to be able to delete the records with FINISH status after a certain time
getTurns() {
fetch('ENPOINT', {
method: 'POST',
body: JSON.stringify({id: this.selected}),
headers: {
'Content-Type': 'application/json'
}
}).then(response => response.json())
.then(data => {
this.turns = data;
data.forEach(turn => {
if(turn.status == 'FINISH'){
setTimeout(() => {
this.turns = data.filter(turn => turn.status !== 'FINISH');
}, 6000);
}
});
})
.catch(error => console.error(error));
}
I have tried going through the array and making a conditional and it works for me, but when I call the method again I get the records with FINISH status again. I need to call the method every time since the data is updated
mounted () {
this.getTurns();
setInterval(() => {
this.getTurns();
}, 5000);
}
maybe I need to order in another way, or that another javascript method I can use
filter is exactly what you need. I don't get why you wrap everything in setInterval and wait for 5 or 6 seconds.
Why don't you return the filtered data instead?
return data.filter(turn -> turn.status !== 'FINISHED');
You mistake in this place
this.turns = data;
It put data in component property turns before filter;
Do it after filter:
.then(data => {
// get before filter
this.turns = data;
// filter data after 6 sec
setTimeout(() => {
data.forEach(turn => {
this.turns = data.filter(turn => turn.status !== 'FINISH');
});
}, 6000)
})
Sorry, but I don't understand why you use setTimeout inside fetch. Do you sure that it necessary?
Code that you need on CodeSandBox. It sure works.
https://codesandbox.io/s/vue-getdata-and-filter-it-after-delay-6yrj16?file=/src/components/HelloWorld.vue
Use filter for your case: turn => turn.status !== 'FINISH'
You can avoid the setTimeout() delay if you take the promise as what it is: a promise that some data will be there!
The following snippet will provide the data in the global variable turns as soon as it has been received from the remote data source (in this example just a sandbox server). The data is then filtered to exclude any entry where the property .company.catchphrase includes the word "zero" and placed into the global variabe turns. The callback in the .then()after the function getTurns() (which returns a promise!) will only be fired once the promise has been resolved.
var turns; // global variable
function getTurns() {
return fetch("https://jsonplaceholder.typicode.com/users")
.then(r => r.json()).then(data =>
turns=data.filter(turn=>!turn.company.catchPhrase.includes("zero"))
)
.catch(error => console.error(error));
}
getTurns().then(console.log);

Pushing to an array is returning index rather then items (React)

I'm trying to add a new object to the end of an array that I'm dynamically fetching over my API. Users complete a form so the data is passed from the form to the state.
The initial first fetch is storing the original array to some react state which is fine, then at some point, a single object should be added to the end of the original array, so the whole array will contain the original data, plus the new object added.
Naturally, I'm trying to use array.push() to try and achieve this, but I keep getting the index rather than the data object.
// declare state will be an array
const [originalPages, setOriginalPages] = useState([]);
// Get all the existing data
loadInitialValues() {
return fetch(`example.com/api/collections/get/testing_features?token=${process.env.REACT_APP_API_KEY}`)
.then((res) => {
return res.json();
})
.then((res)=>{
// set state to be the whole array for this post
setOriginalPages(res.entries[4].pagebuild);
return res.entries[4].pagebuild[0].settings;
})
.catch((err)=>{
console.error(err);
})
}
At this point the data is all working completely fine, the collection of the new data from the forms works fine too. However, this is the point when the data goes to get posted back to update the API but just returns a number:
onSubmit(formData) {
// Dynamically hook all the newly collected form data to this new data object
let theData = {
component: 'page',
settings: {
title: formData.title,
pageOptions: {
pageSideImg: formData.pageOptions.pageSideImg,
isReversed: formData.pageOptions.isReversed,
paraGap: formData.pageOptions.paraGap,
paraFont: formData.pageOptions.paraFont,
},
pageNavigation: {
pageSlug: formData.pageNavigation.pageSlug,
nextPage: formData.pageNavigation.nextPage,
prevPage: formData.pageNavigation.prevPage,
},
globalOptions: {
projectName: formData.globalOptions.projectName,
transType: formData.globalOptions.transType,
menuTrans: formData.globalOptions.menuTrans,
},
blocks: formData.blocks
}
};
cms.alerts.info('Saving Content...');
return fetch(`example.com/api/collections/save/testing_features?token=${process.env.REACT_APP_API_KEY}`, {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: {
// Only returning the array count as a number
pagebuild: originalPages.push(theData),
_id: "610963c235316625d1000023"
}
})
})
.then(response => response.json())
.catch((err) => {
cms.alerts.error('Error Saving Content');
console.log(err);
});
},
If anyone has any ideas as to why this is happening id greatly appreciate it!
For reference, I've checked here and maybe I should use spread instead?
The Array.push doesn't return the final array you would need, but the final length of modified array (that's why you thought it was an index).
Replace this string pagebuild: originalPages.push(theData), with this one:
pagebuild: [...originalPages, theData],
Of course, if you want to update the internal originalPages state value, call this within your onSubmit():
setOriginalPages(x => [...x, theData]);

Object items are not rendering (Object is stored in an array of objects which in turn is stored in a React state hook)

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>)}

fetch gives me a full array but it is empty when i try to access it

I get an object from a Symfony rest API. This object has a property "shooting" which is an array and this array is full when I console.log it but when i try to access it, it is empty
This is my fetch request
const getProjectsAvailable = async () => {
const data = await fetch(
`${process.env.GATSBY_CORE_URI}/api/dashboard/supplier/projects/available`,
{
headers: {
[`X-Auth-Token`]: `${token}`,
[`Accept`]: `application/json`,
},
}
);
return data;
};
Here is the project object that i get back from fetch request
0: {id: 258, name: "Project26-1", reference: "A6568", isOfferValidated: null, source: "dashboard", …}
It has a shooting key which contains an array and it is not empty
shootings: Array(1)
0:
addressCity: "Paris"
addressCountry: {id: 76}
But when i set this object to my component state, all values stay the same except the shooting key which becomes an empty array
const [projects, setProjects] = useState([]);
useEffect(() => {
getProjectsAvailable().then(res =>
res.json().then(data => {
setProjects(data);
})
);
}, []);
I have no idea why does it act like that.
Thanks in advance
EDIT :
For example, the first line with console.log gives me the response object with a full shooting array while the second one sets it to my state but shooting array is empty
useEffect(() => {
getProjectsAvailable().then(response => console.log(response));
getProjectsAvailable().then(response => setProjects(response));
}, []);
Ok it is my bad. Somewhere else in the code, there was a .split() on the shooting property which mutates the array so the props changed and shooting array got empty

Filtering away javascript objects into an array when using fetch

I have a react application, where I use the axios library, to get some values, and set them into an array of javascript objects in my state
componentDidMount(){
axios.get('http://localhost:8080/zoo/api/animals')
.then(res => this.setState({animals: res.data}))
}
Now I want to check if the objects, contains an Owner object, inside it, and filter out does that does,
First, I tried making a const, and then using the filter, to check if they contain the objects, and then set the state, but I can't save my values in a local variable
componentDidMount(){
const animals= [];
axios.get('http://localhost:8080/zoo/api/animals')
.then(res => animals=res.data)
console.log(animals) // logs empty array
console.log('mounted')
}
how can I make it so, that I can only get the animals that do NOT, have an owner object inside it?
Your animal array is empty in your second example because axios.get is asynchronous, what is in your then will be executed once the data is fetch, but the function will keep on going in the meantime.
To filter out your array, simply use filter right after fetching your data :
componentDidMount(){
axios.get('http://localhost:8080/zoo/api/animals')
.then(res => this.setState({animals: res.data.filter(animal => !animal.owner)}))
}
This function will filter out every animal object that does not have an owner property.
Working example :
const animals = [
{
name: 'Simba',
owner: {
some: 'stuff'
}
},
{
name: 1
}, ,
{
name: 2
}, ,
{
name: 3,
owner: {
some: 'stuff'
}
},
{
name: 'Bambi'
//status: 'dead'
}
]
console.log(animals.filter(animal => animal.owner))
EDIT: the answer was changed so that it only filters animals, that does not have an owner

Categories

Resources