I send some http requests and after the Promises have solved I need to loop through the array and to do some async things. I want to leave the function asynchronous but I need to execute setState only after "map" loop is finished:
fetchData = () => {
let data = [];
let tickets = http.get('/api/zendesk/tickets'),
users = http.get('/api/zendesk/users'),
items = http.get('/api/orders/items'),
reqTypes = http.get("/api/support/requests");
Promise.all([users,tickets,items,reqTypes])
.then(values => {
console.log(values);
let usersArr = values[0].data.users,
ticketsArr = values[1].data.tickets,
itemsArr = values[2].data,
requestArr = values[3].data;
data = ticketsArr.map((ticket,key) => {
let id = ticket.custom_fields.find(field => field.id === productions_fields.order_id || field.id === develop_fields.order_id).value;
id === null ? ticket.Items = [] : ticket.Items = itemsArr.filter(item => item.order_id === parseInt(id));
ticket.Requests = requestArr.filter(request => request.id === ticket.id);
})
this.setState({tickets:data})
}).catch(err => console.log(err))
}
Is it possible to do or I need to make sync loop like "for"?
I get an array of "undefined objects", Why?
Because you are not returning anything inside map body, and by default it returns undefined.
Check this snippet:
let a = [1,2,3,4].map(el => {
console.log('el = ', el);
})
console.log('a = ', a); //array of undefined values
If you wants to modify the existing array, then use forEach instead of map.
Like this:
ticketsArr.forEach((ticket,key) => {
let id = ticket.custom_fields.find(field => field.id === productions_fields.order_id || field.id === develop_fields.order_id).value;
ticket.Items = (id === null) ? [] : itemsArr.filter(item => item.order_id === parseInt(id));
ticket.Requests = requestArr.filter(request => request.id === ticket.id);
})
this.setState({ tickets: ticketsArr })
Array.prototype.map expects you to return how each element should be in its final form. Right now you are not returning anything, hence every element becoming undefined.
data = ticketsArr.map((ticket,key) => {
let id = ticket.custom_fields.find(field => field.id === productions_fields.order_id || field.id === develop_fields.order_id).value;
id === null ? ticket.Items = [] : ticket.Items = itemsArr.filter(item => item.order_id === parseInt(id));
ticket.Requests = requestArr.filter(request => request.id === ticket.id);
return ticket // <- this
})
Related
I have a filtering system where I use an array to add or remove the filtering methods. But my state is not working properly or i've missed something.
const [filters, setFilters] = useState([]);
const [creatorFilter, setCreatorFilter] = useState(null);
const handleCreatorFilter =(filter) => {
setCreatorFilter(filter);
if (filter === 'structures' && filters.indexOf(byStructureFilter) === -1) {
setFilters([...filters, byStructureFilter]);
}
if (filter === 'members' && filters.indexOf(byMemberFilter) === -1) {
setFilters([...filters, byMemberFilter]);
}
if (filter === 'all') {
setFilters(filters.filter(el => el !== byStructureFilter || el !== byMemberFilter));
}
};
const byStructureFilter = (item) => {
return item.relationships.structure.data
};
const byMemberFilter = (item) => {
return item.relationships.user.data && !item.relationships.structure.data
};
Here the two buttons calling that handleCreatorFilter for filtering
<button onClick={() => creatorFilter === 'structures' ? handleCreatorFilter('all') : handleCreatorFilter('structures')}>Structures officielles</button>
<button onClick={() => creatorFilter === 'members' ? handleCreatorFilter('all') : handleCreatorFilter('members')} >Membres Wekomkom</button>
The things is for adding filtering methods to the array it works fine but not when the filter is set to all (removing the filtering methods). Do you see something wrong in my logic ?
I'm making a simple movie watchlist application.
I use asyncstorage to save the selected movies.
I want to remove the movie the user has selected in the watchlist section. Right now I am trying this code:
removeItemValue= async (item, index) => {
let value1 = await AsyncStorage.getItem('movies');
value1 =JSON.parse(value1);
console.log("value1"+value)
//value = item.splice(index,1)
if (value1 !== null){
//var index = value.indexOf(x => x.Title === item.Title);
if (index > -1){
value1.splice(index, 1);
await AsyncStorage.removeItem('movies');
AsyncStorage.setItem('movies',JSON.stringify(value));
}
}
}
But this isn't working.
Can you tell me where is wrong?
Also my click part:
removeItemValue = async(index) => { // don't need item here
// avoid mutations, create new variables
const rawValue = await AsyncStorage.getItem('movies');
try {
const jsonValue = JSON.parse(rawValue) || []; // avoid undefined or null
const finalValue = [...jsonValue.slice(0, index), ...jsonValue.slice(index + 1)];
await AsyncStorage.setItem('movies', JSON.stringify(finalValue)); // add await here
} catch (e) {
console.log('Parsing failed', e)
}
}
And remove using () => this.removeItemValue(index)
Pleas try this
var moviesArray = [{title:'A1'},{title:'A2'},{title:'A3'},{title:'A4'},{title:'A5'},{title:'A6'},{title:'A7'},]
removeSelectedMovie=(name)=>{
return moviesArray.filter(item=>item.title.toLowerCase() !== name.toLowerCase())
}
//removeSelectedMovie(MovieName here and its will return a //new array excluded selected movie name)
console.log(removeSelectedMovie('a1'))
console.log(removeSelectedMovie('a3'))
console.log(removeSelectedMovie('a4'))
console.log(removeSelectedMovie('a7'))
There are 2 components:
a filter component that sets the state
an output component that renders items based on the filters
There are 2 arrays:
an array of all items
an array of the selected filtered options.
let itemsFiltered;
if (this.state.continent !== "") { itemsFiltered = items.filter( (item) => item.continent == this.state.continent ); }
if (this.state.country !== "") { itemsFiltered = items.filter( (item) => item.country == this.state.country ); }
if (this.state.region !== "") { itemsFiltered = items.filter((item) => item.region == this.state.region); }
if (this.state.activity !== "") { itemsFiltered = items.filter((item) => item.activity == this.state.activity); }
if (this.state.skill !== "") { itemsFiltered = items.filter((item) => item.skill == this.state.skill); }
PROBLEM: it does not work for skill and region. for skill it works if it is selected first, but not if other selections have already been made. For regions it simply doesn't apply the filters at all. Hence it simply shows all items independent of the filter set. It works for all the other filters and combinations of them.
this is what the data looks like (dummy):
{
title: "Item 1",
description: "Description of the item",
image: imageItem1,
continent: "europe",
country: "portugal",
region: "norte",
activity: "kite",
skill: "proLocal",
},
How would you write this to make it work? Should the filters be ordered differently or is there another approach I'm missing?
Extension (code to comments below): Trying to iterate thru the filters fails because you cannot iterate thru the state object:
let itemsFiltered = items.slice();
const filtersSet = ["continent", "country", "region", "activity", "skill"]
for (let i = 0; i < filtersSet.length; i++) {
if (this.state.filtersSet[i] !== "") {itemsFiltered = itemsFiltered.filter( item => item.filtersSet[i] == this.state.filtersSet[i] );}
}
Issue
Doesn't seem like filtering by more than any single filter should work as each filter operation completely overwrites any previous filtering results.
let itemsFiltered;
if (this.state.continent !== "") {
itemsFiltered = items.filter(
(item) => item.continent == this.state.continent
);
}
if (this.state.country !== "") {
itemsFiltered = items.filter((item) => item.country == this.state.country);
}
if (this.state.region !== "") {
itemsFiltered = items.filter((item) => item.region == this.state.region);
}
if (this.state.activity !== "") {
itemsFiltered = items.filter((item) => item.activity == this.state.activity);
}
if (this.state.skill !== "") {
itemsFiltered = items.filter((item) => item.skill == this.state.skill);
}
Solution
You can filter each subsequent filter from the result of the previous filter operation.
let itemsFiltered = items.slice();
if (this.state.continent !== "") {
itemsFiltered = itemsFiltered.filter(item => item.continent === this.state.continent);
}
if (this.state.country !== "") {
itemsFiltered = itemsFiltered.filter(item => item.country === this.state.country);
}
if (this.state.region !== "") {
itemsFiltered = itemsFiltered.filter(item => item.region === this.state.region);
}
if (this.state.activity !== "") {
itemsFiltered = itemsFiltered.filter(item => item.activity === this.state.activity);
}
if (this.state.skill !== "") {
itemsFiltered = itemsFiltered.filter(item => item.skill == this.state.skill);
}
or to save a lot of array iterations do it all in a single filter function.
const itemsFiltered = items.filter((item) => {
if (this.state.continent) return item.continent === this.state.continent;
if (this.state.country) return item.country === this.state.country;
if (this.state.region) return item.region === this.state.region;
if (this.state.activity) return item.activity === this.state.activity;
if (this.state.skill) return item.skill === this.state.skill;
return true;
});
i have the following code but the slice function is not working as expected
for (const id of input.campaignIds) {
exsitingAffiliates = context.metadataService
.getAffiliates("'" + id + "'", ChimdsdseraCollection.Campaigns)
.catch(() => null)
exsitingAffiliates.then(result => {
for (const affiliate of apiInput) {
const affiliatesDB = result.map(a => a.a_list_fk_i_id_tbl_affiliates)
const mode = result.map(campaign => campaign.e_list_affiliate_mode)
let DbAffiliates = JSON.parse(affiliatesDB[0].replace(/\'/gi, ''))
let found = DbAffiliates.includes(affiliate)
if (found) {
if (mode == 'WHITE') {
console.log(affiliate)
console.log('DbAffiliates'+DbAffiliates)
finalArray1 = DbAffiliates.slice(affiliate)
console.log('FINAL array' + finalArray1)
this returns
2
DbAffiliates1,5,2,3
FINAL array2,3
1
DbAffiliates1,5,2,3
FINAL array5,2,3
when it should return
2
DbAffiliates1,5,2,3
FINAL array1,5,3
1
DbAffiliates1,5,2,3
FINAL array 5,3
i tried everything but it doesn't seem to work
I get an “infinite update loop in a component render function” and it seems to be triggered by a vuex getter but I have seriously no idea why. Any hint would help me a lot
getPlanningsForPlanner: (state, getters, rootState, rootGetters) => () => {
let people = getters['getPeopleOrderedBy']();
return rootState.plannings.map((planning) => {
if (planning.adhoc_text === null) {
planning.epic = rootGetters['moduleJIRA/getEpicByKey'](planning.epic_key);
if (typeof (planning.epic) !== 'undefined')
planning.project = rootGetters['moduleJIRA/getProjectByKey'](planning.epic.fields.project.key)
} else {
planning.epic = {};
planning.project = {};
}
// parse dates
planning.startDate = moment(planning.start_date);
planning.endDate = moment(planning.end_date);
// add people
planning.people = people.find(elm => elm.id === planning.people_id);
// calculation of hours
planning.dailyHours = getters['daysToHours'](1, planning.load);
planning.businessDays = planning.startDate.businessDiff(planning.endDate) + 1;
planning.plannedHours = getters['daysToHours'](planning.businessDays, planning.load);
if (!planning.pinned_end) {
let fixPlannedEpics = rootState.plannings.filter(_planning => _planning.epic_key === planning.epic_key && _planning.pinned_end);
let fixPlannedHours = fixPlannedEpics.reduce((sum, _planning) => sum + _planning.plannedHours, 0);
let openlyPlannedEpics = rootState.plannings.filter(_planning => _planning.epic_key === planning.epic_key && !_planning.pinned_end);
let hours = Math.max((planning.epic.budget - planning.epic.sumTimeSpent - fixPlannedHours) / openlyPlannedEpics.length, planning.dailyHours);
planning.endDate = moment(planning.startDate).businessAdd(Math.round(hours / planning.dailyHours));
}
// add indices in timeBeam
let indices = getters['getIndices'](planning.startDate, planning.endDate);
planning.startIndex = indices.start;
planning.endIndex = indices.end;
return planning
});
},