React Hooks- forEach of an array doesn't work - reactjs

I'm working in a project using React hooks. However I try to use a variable without useState hook to handle a variable. The thing is that when I'm running a function that contains an array operation, it seems like that is not took into account and skip that step.
I did the change that way (you'll see that soon in the code) because I'm using an array that is continuos adding more values, so I think that is easier to do in that way.
Can you please help me to fix that issue or explain me why is that doesn't working?
Here is the code:
let platosRegVent:any = []; // This is how I'm declaring my array
const agregarPlato = async () => {
if(validarCamposPlato()){
try{
let valorParcial = 0;
let platoExist = await encontrarPlato(config, rvPlato);
if(platoExist === true){
setAgregadoMin(true);
platoCodigo = await obtenerCodigoPlato(config, rvPlato);
platosRegVent.push({codigoPlato: platoCodigo, cantidad: rvCantidad}); // Here is where I'm adding more objects to my array.
let costoPlato = await obtenerValorPlato(config, rvPlato);
valorParcial = valorTotal;
setValorTotal(valorParcial += (costoPlato * parseInt(rvCantidad)));
setRvPlato('');
setRvCantidad('');
}
else{
toast.error('El plato ingresado no se ha encontrado.');
setRvPlato('');
}
}
catch(error){
toast.error('Un error inesperado ha ocurrido, por favor intente mas tarde.');
props.handleSubmit();
}
}
}
const finalizarRegVent = async () => {
console.log(agregadoMin);
if(validarCampos()){
try{
if(rvPlato !== '' || rvCantidad !== ''){
await agregarPlato();
}
if(agregadoMin === true){
rvCodigo = await crearRegistroVenta(config, valorTotal, fechaActual, regVentMesa);
platosRegVent.forEach( (plato : any) => { //Here is the operation of the array. It seems that this step is skipped.
crearRegVentPlato(config, rvCodigo, plato.codigoPlato, plato.cantidad);
});
setValorFinal(false);
}
else{
toast.error('Debe ingresar por lo menos un plato para completar el registro.');
}
}
catch(error){
toast.error('Un error inesperado ha ocurrido, por favor intente mas tarde.');
props.handleSubmit();
}
}
}

You should use useState() & useCallback() hook instead.
Because the mechanism of React only updated when detecting the change of state. If you create static variable, react can't update its value.
Alternatively, useRef() is solution for you.

Related

Random gif and icon

I made a script that, when a user updates their profile, sends their new avatar to a channel based on the image extension. It's working when the extension is .png, but when it's .gif it sends it in the same channel where it sends the .pngs. My code is below:
Versao Pt
fiz um script pra quando um usuario alterar seu avatar o bot enviar ele em um canal, ta funcionando mas quando é .png o bot envia certinho, mas qunado é .gif ele envia no canal do .png e na mesma embed.
client.on('userUpdate', (oldUser, newUser) => {
const oldAvatarURL = oldUser.displayAvatarURL({ size: 2048, dynamic: true });
const newAvatarURL = newUser.displayAvatarURL({ size: 2048, dynamic: true });
if (oldAvatarURL === newAvatarURL) return;
const avatarExtension = newAvatarURL.split('.').pop();
const canalgif = client.channels.cache.get("1076541628405272667");
const canalicon = client.channels.cache.get("1076541589062692874");
//-----------------------------// GIFS //-----------------------------//
if (avatarExtension === 'gif') {
const embedgif = new Discord.EmbedBuilder()
.setImage(newAvatarURL)
.setColor('#360d60')
.setTitle('Teste gif');
canalgif.send({ embeds: [embedgif] });
} else {
//-----------------------------// Icon //-----------------------------//
const embedicon = new Discord.EmbedBuilder()
.setImage(newAvatarURL)
.setColor('#360d60')
.setTitle('teste icon');
canalicon.send({ embeds: [embedicon] });
}
});
you just need to remove the size parameter of both oldAvatarURL and newAvatarURL variable.
Indeed, with your code, a gif will be shown as gif?size=4096...
If you use .displayAvatarURL() with the size option, the URL returned will append a query string at the end. It means the avatar won't end with .gif, .png, .webp etc but with .webp?size=2048.
The way you're currently getting the extension of the URL won't work as you just split that by a . and check the last part.
// ⛔️ won't work
let url = `https://cdn.discordapp.com/avatars/827997777303699467/55b85c4fe590a54c53183990b030f128.webp?size=2048`
let extension = url.split('.').pop();
console.assert(extension === 'webp', `extension is not "webp", but "${extension}"`);
Instead of removing the size option where you end up with the default size of 128px, you could update the way you grab the extension. First, you could split by that . you already tried, then you could split again by ?:
// ✅ works as expected
let url1 = `https://cdn.discordapp.com/avatars/827997777303699467/55b85c4fe590a54c53183990b030f128.webp?size=2048`;
let url2 = `https://cdn.discordapp.com/avatars/827997777303699467/55b85c4fe590a54c53183990b030f128.png`;
let extension1 = url1.split('.').pop().split('?')[0];
let extension2 = url2.split('.').pop().split('?')[0];
console.log(extension1);
console.log(extension2);
So, the following should work as expected:
client.on('userUpdate', (oldUser, newUser) => {
const options = { size: 2048, dynamic: true };
const oldAvatarURL = oldUser.displayAvatarURL(options);
const newAvatarURL = newUser.displayAvatarURL(options);
if (oldAvatarURL === newAvatarURL) return;
const avatarExtension = newAvatarURL.split('.').pop().split('?')[0];
const embed = new Discord.EmbedBuilder()
.setImage(newAvatarURL)
.setColor('#360d60');
if (avatarExtension === 'gif') {
const canalGif = client.channels.cache.get('1076541628405272667');
canalGif.send({ embeds: [embed.setTitle('Teste gif')] });
} else {
const canalIcon = client.channels.cache.get('1076541589062692874');
canalIcon.send({ embeds: [embed.setTitle('Teste icon')] });
}
});

Nested onSnapshot problem in react-native-Firebase Firestore

I'm struggling to overcome problems that I have on nested onSnapshot, so, in short, I have 3 nested onSnapshot and when parent/root onSnapshot updates it also creates new onSnapshot listeners and leaves old ones too, so old and new ones are listening to the changes. I know that I should unsubscribe it but I can't, I'm losing track of which listeners are added or already exist.
One solution is to create array of unsubscribing functions in parent onSnapshot, but there another problem comes, I'm using docChanges with forEach and it is hard to manage which would I unsubscribe from array.
I saw this on Stackoverflow but it doesn't fit mine or even doesn't explain correctly exactly this case: nested listeners
What can you suggest to me? I don't know what else should I do.
Thanks in advance.
here is an example of my code that I'm trying to implement unsubscribe stuff( I use Mobx):
// TODO: optimise this query
const id = auth().currentUser?.uid;
// get all channelId-s that user has
channelParticipantsRef
.where('user.id', '==', id)
.onSnapshot((userChannels) => {
userChannels?.docChanges().forEach(function (channelParticipant) {
const channelParticipantData = channelParticipant;
if (!channelParticipantData.doc.exists) return;
// get all channels data that user has
channelsRef
.where(
'channelId',
'==',
channelParticipantData.doc.data().channelId,
)
.onSnapshot((channels) => {
if (!channels || channels.empty) return;
channels.docChanges().forEach(function (channel) {
const channelDataObject = channel.doc.data();
console.logBeauty(channel.type, 'channelDataObject ');
if (channel.type === 'added' || channel.type === 'modified') {
const channelData: ChannelTransformedDataType = {
...channelDataObject,
language: channelParticipantData.doc.data().language,
channelParticipantId: channelParticipantData.doc.id,
lastMessageDate: {
...channelDataObject.lastMessageDate,
},
otherUsers: [],
};
// get all channels users
channelParticipantsRef
.where('user.id', '!=', id)
.where('channelId', '==', channelDataObject.channelId)
.onSnapshot((channelParticipants) => {
const participants: UserModelType[] = [];
if (channelParticipants.empty)
return self.removeChannel(
channelDataObject.channelId,
);
channelParticipants.docs.forEach(
(channelParticipant) => {
participants.push(channelParticipant.data().user);
},
);
channelData.otherUsers = participants;
console.log(channelData, 'channelDatachannelData');
if (channel.type === 'added')
self.pushChannel(channelData);
else self.editChannel(channelData);
});
} else if (channel.type === 'removed') {
self.removeChannel(channelDataObject.channelId);
}
});
});
});
});

How to use a function's variables in other functions?

I need to get several variables declared in a function A to use it in a function B.
How can I do that with ReactJS ?
EDIT
Function A :
const FunctionA = (e) => {
setPopupOpen(true)
e.preventDefault()
// data du cartouche en cours
let dataDest = e.currentTarget.getAttribute('data')
let jdataDest = JSON.parse(dataDest)
let channelDest = jdataDest.channel
let numcartDest = jdataDest.data.NUM_CART
// data de l'item en cours de drag
let tot = e.dataTransfer.getData("mydatabrowser")
if (tot) { // d&d externe depuis browser
let dataItem = JSON.parse(tot)
console.log(dataItem)
console.log("drop from browser", dataItem)
//execution d&d externe
InsertItem(callbackDrag, props.ddo, dataItem.val.guid, channelDest, numcartDest, dataItem)
}
else { // d&d interne entre cartouches
FunctionB(dataOrig, dataDest)
}
}
e.dataTransfer.clearData()
if (!tot) {
//*
}
}
Function B :
const FunctionB = (dataOrig, dataDest) => {
if (dataOrig, dataDest) {
if (dndReplace) {
ReplaceItem(callbackDrag, props.ddo, dataItem.data.GUID_ITEM, channelDest, numcartDest, dataItem)
} else {
InsertItem(callbackDrag, props.ddo, dataItem.val.guid, channelDest, numcartDest, dataItem)
}
}
}
Functions A and B are in the same component.
I call the function A in a PopUp component.
Variables I need to get are dataDest and dataOrigin.
Assign all variables to Array or Object and pass it as parameter to the function B, if the function B is a functional component then you can pass it as props.
Please share your code so we can solve it and explain the solution with your code as an example :)

Cannot read the property 'roles' of undefined

I'm making a bot and I have an error that I don't understand in this code : pas
const Discord = require("discord.js");
const client = new Discord.Client();
const token = "";
client.login(token)
client.on("message", async(message) => {
let staffRole = message.guild.roles.find("name", "Staff");
let staff = message.guild.member(message.author);
if (message.author.id === "424974772959444993" || message.member.roles.has(staffRole.id)) {
return;
}
var badWords = [
'asd',
'legionmods',
'verga',
'vrga',
'nmms',
'alv',
'electromods',
'remake'
];
var words = message.content.toLowerCase().trim().match(/\w+|\s+|[^\s\w]+/g);
var containsBadWord = words.some(word => {
return badWords.includes(word);
});
if (containsBadWord) {
message.delete();
message.author.send({embed: {
color: 3447003,
description: `Has dicho una palabra que no esta permitida en este servidor`
}
message.channel.send(`${prefix}tempmute ${message.author}`+" 5m palabra prohibida")
}
});
This is an error I get :
(node:4952) UnhandledPromiseRejectionWarning: TypeError: Cannot read property
'roles' of null
at Client.client.on (C:\Users\Francisco\Desktop\role\app.js:8:33)
Could someone help me please ? I am not good in debugging errors.
message.guild is probably returning null because the message was sent in a dm conversation, not a guild.
You can avoid this problem by writing:
if (message.channel.type !== 'text') return;
Also, a few GuildMemberRoleManager methods have changed a bit since discord.js v12+. You should replace:
let staffRole = message.guild.roles.find("name", "Staff");
With:
let staffRole = message.guild.roles.cache.find(role => role.name === "Staff");
And replace:
message.member.roles.has(staffRole.id)
With:
message.member.roles.cache.has(staffRole.id)

how to form an object and push it into an array using http/https from the resultant of response

i am new to nodejs and i am trying to form an array of products which are having invalid imageUrls by using "http.get", I am querying my products from my mongodb collection, though i used "Promise" the array is printing first, i am not getting the result form the "hh.get"
here is my code in server side
var Promise = require('bluebird'),
hh = require('http-https')
mongoose = require('mongoose'),
collection = mongoose.model('Collection');
function getInValidImgUrl(prodObj){
return hh.get(prodObj.imageUrl,function(res){
if(res.statusCode == 404){
return {
name:prodObj.name,
imgUrl:prodObj.imageUrl
}
}
})
}
exports.sampleFunc=function(){
collection.find({category:"electronics"}).exec(function(err,products){
if(err){
console.log(err)
}else{
var imgArr=[];
//eg:products=[{name:"mobile",imageUrl:"http://somepic.jpg"}]
for(var i=0; i<products.length: i++){
imgArr.push(getInValidImgUrl(products(i)));
}
Promise.all(imgArr).then(results =>{
console.log("IAMGE ARRAY :"+JSON.stringify(results)); //here iam not getting array
})
}
});
}
thanks in advance.
You don't actually need to use bluebird for this, although you could use the npm package request-promise (https://www.npmjs.com/package/request-promise) I use that quite a lot. In the interests of not changeing what you have too much your issue is that you are making the return in the callback for the getInValidImgUrl function. You can change this to use the standard Promise class that comes for free with node (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
function getInValidImgUrl(prodObj){
return new Promise((resolve,reject) => {
hh.get(prodObj.imageUrl,function(res){
if(res.statusCode == 404){
resolve( {
name:prodObj.name,
imgUrl:prodObj.imageUrl
})
}
})
}
}

Resources