how can i delete multiples request at the same time using axios and an array of URL - reactjs

im doing an app and the first code is working deleting a "task" in my API, but in my app each task have a checkbox input, so, i want to delete all the tasks that are checked.
i used this code to delete single task with a button.
const baseURLtasksId = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${taskId}`
axios.delete(baseURLtasksId, { done: true }).then()
}
ArrayUrlById this is an array of all the URL's that are checked
const deleteAll = () => {
let ArrayUrlById = []
ArrayUrlById = isChecked.map((cId) => {
let arrayURL = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${cId}`
return arrayURL
})
console.log(ArrayUrlById); // here i have an array of the URL
// i need to delete now multiples tasks, using an array of URL and sending {done:true} for each one
}
i tried with this code, but not working properly, beacuse never delete all of them, even in the console send all the delete request to the endpoint with a 200 status, but after i refresg the website, is not deleting all of them that are checked
const deleteAll = () => {
let ArrayUrlById = []
console.log('aqui');
ArrayUrlById = isChecked.map((c) => {
let arrayURL = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${c}`
return arrayURL
})
console.log(ArrayUrlById);
const requests = ArrayUrlById.map(url => axios.delete(url));
axios.all(requests)
.then(responses => {
responses.forEach(response => console.log(response.data));
})
.catch(error => {
console.log(error);
})
}
enter image description here

Related

discord js I need to fetch and delete messages more than discord limit (100) allows

let purgingCounter = splitMsg[1];
function purging() {
client.channels.cache.get(channelTarget).messages.fetch({ limit: [1]})
.then(data => {
let messageArr = [...data];
console.log(messageArr[0][1]);
console.log(`Second log ${messageArr[0][1].id}`);
client.channels.cache.get(channelTarget).messages.delete(messageArr[0][1].id);
console.log(`purged`);
purgingCounter-=1;
})
.then(() => {
if (purgingCounter>0) {
purging();
}
});
};
purging();
Once deleted I want to check if user wanted to delete more than set limit and repeat the function (because discord has a limit of 100), but it gets called twice and ends up crashing after deleting one message.
async function purging (counter) {
let data = await client.channels.cache.get(channelTarget).messages.fetch({ limit: [100]})
let messageArr = [...data];
for (let i=0; i<messageArr.length; i++) {
console.log(`Ids purging: ${messageArr[i][1].id}`);
await client.channels.cache.get(channelTarget).messages.delete(messageArr[i][1].id);
counter-=1;
if (counter<=0) {
return;
}
};
//Check if user wanted to delete more than limit, Timeout makes sure it's the last bit of code to execute
setTimeout(() => {
console.log(`calling back ${counter}`);
if (counter>0) {
purging(counter);
} else { return };
}, 1);
}
purging(splitMsg[1]);
basically this is what I wanted, it works, it deletes messages over limit and doesn't delete more than asked.

getDownloadURL in array of dictionary (re-rendering issue, forEach)

I have an array of dictionaries, (e.g. [{}, {}, {}, {}], each dictionary contains information about book)
I want to download image from firebase storage using getDownloadURL.
My current code's like...
const [resObj, setresObj] = useState() // empty variable for update state
let result = [] //create empty array for copy & push new obj
useEffect(() => {
props.resObj.forEach((obj) => { // props.resObj: array of dictionary I explained before
const jpgName = 'bookDB/'+ obj.도서번호 + '.jpg';
const imgRef = ref(storage, jpgName)
getDownloadURL(imgRef)
.then((url) => {
result1.push({
...obj,
bookUrl: url
}) // copy & push dictionary
})
.catch((error) => {
if (error.code === 'storage/object-not-found') {
console.log('이미지 파일 없음')
result1.push({
...obj,
bookUrl: "https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg"
})
} else { console.log(error)}
})
})
setresObj(result1)
}, [])
after this code update 'resObj' variable,
I map resObj in component like...
return (
<div>
{resObj? resObj.map(item => {
<img
key = {}
className = '~~'
onClick = {}
src = {item.bookUrl}
/>
})}
</div>
)
unfortunately.. it doesn't show nothing..
It seems that forEach, useEffect, useState, getDownloadURL Promise seriously entangled..
I tried 1) devide download image code as function, 2) devide download image code as recoil, 3) escape download image code from useEffect, 4) ...(extra variances of code)...
The problem is that your call to setresObj happens before any of the calls to result1.push have happened, so you're always setting an empty array. It's easiest to verify this by setting breakpoints and running in the debugger, or by adding some console.log calls.
The fix is to use Promise.all to wait for all download URLs to have been retrieved and only then call setresObj. Something like this:
useEffect(() => {
let promises = props.resObj.map((obj) => {
const jpgName = 'bookDB/'+ obj.도서번호 + '.jpg';
const imgRef = ref(storage, jpgName)
return getDownloadURL(imgRef)
.then((url) => {
return {
...obj,
bookUrl: url
}
})
.catch((error) => {
if (error.code === 'storage/object-not-found') {
console.log('이미지 파일 없음')
result1.push({
...obj,
bookUrl: "https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg"
})
} else { console.log(error)}
})
})
Promise.all(promises).then((results) => {
setresObj(results);
});
}, [])

Submitting a form Firebase for details of a Product with an array of multiple images with getDownloadURL and setting to State (productThumbnail)

Going into the debugger of the developer tools shows 2 problems:
Cannot read property .then of undefined
It also shows that the TWO files are being 'put' to storage 2 separate instances, which I believe causes the dispatch addProductStart to also run twice.
moving the setProductThumbnail((prevState)... down a line removes the .then undefined error, but also results in addProductStart running twice. Resulting in 2 products being made instead of 1 product with multiple images.
So to solve this, the handleSubmit function needs to be refactored to where getDownloadURL is able to put 2 URLs into an array, and set to State productThumbnail, so that products can be uploaded with multiple images attached in Firestore Collection
const productImgHandler = (e) => {
for (var i = 0; i < e.target.files.length; i++) {
const selectedFiles = e.target.files[i];
selectedFiles["id"] = Math.random();
setpreProductThumbnail((prevState) => [
...prevState,
selectedFiles,
]);
console.log(selectedFiles);
}
};
const handleSubmit = (e) => {
const promises = [];
e.preventDefault();
preproductThumbnail.map((image) => {
promises.push(storage().ref(`prodimages/${image.name}`).put(image));
storage()
.ref(`prodimages/${image.name}`)
.put(image)
.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) *
100;
console.log(progress);
},
(err) => {
setError(err.message);
},
() => {
storage()
.ref("prodimages")
.child(image.name)
.getDownloadURL()
setProductThumbnail((prevState) => [...prevState, productThumbnail])
.then((productThumbnail) => { // put an array in here, then change fetch function on Productpage
console.log("PRODTHUMB2", productThumbnail);
dispatch(
addProductStart({
productCategory,
productName,
productThumbnail,
productPrice,
productDesc,
})
);
}, resetForm());
}
);
});```
setProductThumbnail does not return a promise to then .then() promise chain onto.
You should be processing the setProductThumbnail inside the .then() statement instead.

How could I write this function so it doesn't setState within the foreach everytime

The function collects role Assignment PrincipalIds on an item in SPO. I then use a foreach to populate state with the Title's of these PrincipalIds. This all works fine but it's inefficient and I'm sure there is a better way to do it than rendering multiple times.
private _permJeChange = async () => {
if(this.state.userNames){
this.setState({
userNames: []
});
}
var theId = this.state.SelPermJEDD;
var theId2 = theId.replace('JE','');
var info = await sp.web.lists.getByTitle('MyList').items.getById(theId2).roleAssignments();
console.log(info, 'info');
var newArr = info.map(a => a.PrincipalId);
console.log(newArr, 'newArr');
// const userIds = [];
// const userNames = [];
// const userNameState = this.state.userNames;
newArr.forEach(async el => {
try {
await sp.web.siteUsers.getById(el).get().then(u => {
this.setState(prevState => ({
userNames: [...prevState.userNames, u.Title]
}));
// userNames.push(u.Title);
// userIds.push(el);
});
} catch (err) {
console.error("This JEForm contains a group");
}
});
}
I've left old code in there to give you an idea of what I've tried. I initially tried using a local variable array const userNames = [] but declaring it locally or even globally would clear the array everytime the array was populated! So that was no good.
PS. The reason there is a try catch is to handle any SPO item that has a permissions group assigned to it. The RoleAssignments() request can't handle groups, only users.
Create an array of Promises and await them all to resolve and then do a single state update.
const requests = info.map(({ PrincipalId }) =>
sp.web.siteUsers.getById(PrincipalId).get().then(u => u.Title)
);
try {
const titles = await Promise.all(requests);
this.setState(prevState => ({
userNames: prevState.userNames.concat(titles),
}));
} catch (err) {
console.error("This JEForm contains a group");
}

Firestore: calling collections.get() inside promise()

useEffect(() => {
if (!stop) {
// get current user profile
db.collection('events').get(eventId).then((doc) => {
doc.forEach((doc) => {
if (doc.exists) {
let temp = doc.data()
let tempDivisions = []
temp["id"] = doc.ref.id
doc.ref.collection('divisions').get().then((docs) => {
docs.forEach(doc => {
let temp = doc.data()
temp["ref"] = doc.ref.path
tempDivisions.push(temp)
});
})
temp['divisions'] = tempDivisions
setEvent(temp)
setStop(true)
// setLoading(false);
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
<Redirect to="/page-not-found" />
}
})
})
}
}, [stop, eventId]);
I am curious if this is the properly way to extract nested data from Cloud Firestore.
Data model:
Collection(Events) -> Doc(A) -> Collection(Divisions) -> Docs(B, C, D, ...)
Pretty much I'm looking to get metadata from Doc(A), then get all the sub-collections which contain Docs(B, C, D, ...)
Current Problem: I am able to get meta data for Doc(A) and its subcollections(Divisions), but the front-end on renders metadata of Doc(A). Front-End doesn't RE-RENDER the sub-collections even though. However, react devtools show that subcollections(Divisions) are available in the state.
EDIT 2:
const [entries, setEntries] = useState([])
useEffect(() => {
let active = true
let temp = []
if (active) {
divisions.forEach((division) => {
let teams = []
let tempDivision = division
db.collection(`${division.ref}/teams`).get().then((docs) => {
docs.forEach((doc, index) => {
teams.push(doc.data())
})
tempDivision['teams'] = teams
})
setEntries(oldArray => [...oldArray, temp])
})
}
return () => {
active = false;
};
}, [divisions]);
is there any reason why this is not detecting new array and trigger a new state and render? From what I can see here, it should be updating and re-render.
Your inner query doc.ref.collection('divisions').get() doesn't do anything to force the current component to re-render. Simply pushing elements into an array isn't going to tell the component that it needs to render what's in that array.
You're going to have to use a state hook to tell the component to render again with new data, similar to what you're already doing with setEvent() and setStop().

Categories

Resources