So I'm trying to run a comparison statement with the firebase SDK.
I've got a function which checks if the phone number or email has a valid invite value / document exists within the database.
I want to add a comparison that says if the invitationData is valid and the claimedDate value is not equal to the data type null or the invitationData is valid and the string value is not equal to null then alert invitation not confirmed. The problem I'm having is with the || or operator I can only seem to get this comparison to work if I'm just doing one argument when I add the or it stops working.
async function checkInvitation(email = '', phone = '') {
try {
let snapshot = firebase.firestore().collection(COLLECTIONS.INVITATIONS);
if (email) {
snapshot = snapshot.where('email', '==', email);
} else if (phone) {
snapshot = snapshot.where('phone', '==', phone);
}
let invitationData = await snapshot.get();
if (!invitationData || invitationData.docs.length === 0) {
Alert.alert(
'Invitation not confirmed',
'Please try again or join our waiting list.',
);
return false;
}
if ((invitationData && invitationData.docs[0].data().claimedDate !== null) || (invitationData && invitationData.docs[0].data().claimedDate != "somestring")) {
Alert.alert(
'Invitation not confirmed',
'This invitation has already been used',
);
return false;
}
return invitationData.docs[0].id;
} catch (error) {
console.log(error);
throw new Error(error);
}
}
If you shorten it (excuse the pseudo nature) it looks as follows :
if (claimedDate !== null || claimedDate != "somestring")
I'm pretty sure that's not what you are meaning. Perhaps you are intending an AND?
Related
JavaScript is known to only check the first variable in a && comparison in case the first variable returns false. Is there a way to 'ask' JavaScript to check both variables i.e. when they are methods?
For example: Suppose you have 2 methods that validate 2 separate user inputs:
const validateEmail = value => {
if(value.contains('#')){
setShowEmailError(false);
return true;
}
setShowEmailError(true);
return false;
};
const validatePswd = value => {
if(value !== ''){
setShowPswdError(false);
return true;
}
setShowPswdError(true);
return false;
};
Then check both conditions:
if(validateEmail(email) && validatePswd(pswd)){
//validate entire form and render errors
}
However, the above will not execute the validatePswd method if the first method validateEmail returns false.
Is there a way to check if both values are true and run both methods? Having JavaScript run both methods would be a breeze in some cases.
You can execute them in an array and then accumulate the result with && by reduce function.
const validateEmail = value => {
if(value.includes('#')){
//setShowEmailError(false);
return true;
}
//setShowEmailError(true);
console.log('wrong email')
return false;
};
const validatePswd = value => {
if(value !== ''){
//setShowPswdError(false);
return true;
}
// setShowPswdError(true);
console.log('wrong password');
return false;
};
// you can execute any number of validations within the array.
const result = [validateEmail('something'), validatePswd('')].reduce((acc, f) => acc && f, true);
console.log(result)
UPDATE
Or as #lux suggested using every method.
const validateEmail = value => {
if(value.includes('#')){
//setShowEmailError(false);
return true;
}
//setShowEmailError(true);
console.log('wrong email')
return false;
};
const validatePswd = value => {
if(value !== ''){
//setShowPswdError(false);
return true;
}
// setShowPswdError(true);
console.log('wrong password');
return false;
};
// you can execute any number of validations within the array.
const result = [validateEmail('something'), validatePswd('')].every(r => r);
console.log(result)
I don't know if you are looking for something like this:
const valEmail = validateEmail(email);
const valPsw = validatePswd(pswd);
if(valEmail && valPsw ){
//validate entire form and render errors
}
I work on a project where we receive error messages from the backend. Sometimes the error messages are not frontend friendly. We are doing some work to tidy these up, but in the meantime I created a function that takes the error message and replaces any values.
I want to make the function re-usable for other error messages and wondered if anyone has any advice.
Here is the function with 1 error message currently.
Error message entered: 'Minimum payment_amount is $10.'
Error message being returned: 'Minimum payment amount is $10.'
const errorMessageConvertor = (errorMessage) => {
if (errorMessage !== undefined) {
const convertedErrorMessage = errorMessage.toString();
return convertedErrorMessage.replace("payment_amount", "payment amount");
}
};
Maybe something like that
const errorMessageConvertor = (errorMessage, keyToReplace, valueToReplace) => {
if (errorMessage !== undefined) {
const convertedErrorMessage = errorMessage.toString();
return convertedErrorMessage.replace(keyToReplace, valueToReplace);
}
};
// usage
errorMessageConvertor('Minimum payment_amount is $10.','payment_amount','payment amount')
If you only want to get rid of underscores then this should solve the problem, it will replace all the underscores with spaces.
const errorMessageConvertor = (errorMessage) => {
if (errorMessage !== undefined) {
const convertedErrorMessage = errorMessage.toString();
return convertedErrorMessage.replaceAll('_', ' ');
}
};
database()
.ref('/')
.once('value')
.then(snapshot => {
var user = snapshot.val().users.filter(x => x.mail == mail)[0];
if (user != undefined && user != null)
{
ToastAndroid.show("User is there !", ToastAndroid.SHORT);
}
else
{
//Add user
}
I want to search this user with mail address and if the user is not there i will add it.But I get this error.
TypeError: snapshot.val().users.filter is not a function. (In 'snapshot.val().users.filter(function (x) { return x.mail == mail; })', 'snapshot.val().users.filter' is undefined)
As mentioned in the comments NEVER try to load all data to filter it on the client side. You can use orderByChild query to filter on the database to a specific reference in users to get only the one with the email you search for. The code would look something like this:
database()
.ref('/users')
.orderByChild('email')
.equalTo(email)
.limitToLast(1)
.once('value')
.then(snapshot => {
var user = snapshot.val()
if (user != undefined && user != null)
{
ToastAndroid.show("User is there !", ToastAndroid.SHORT);
}
else
{
//Add user
}
how to fix this error
music.on('voiceStateUpdate',(lama, baru) => {
var state = null;
let Role = baru.roles.find((r) => ["IRON", "BRONZE"].includes(r.name));
const kategorikanal = '700743802574602260'
const channelid = '700743824346972231'
if(!lama.voiceChannel && !baru.voiceChannel) return;
if(!lama.voiceChannel && baru.voiceChannel) {state = "join"}
else if(lama.voiceChannel && !baru.voiceChannel) {state = "leave"}
else if(lama.voiceChannel.id !== baru.voiceChannel.id) {state = "move"}
else if(lama.voiceChannel.id == baru.voiceChannel.id) return;
console.log(state);
//!baru.member.roles.has(allowedRole)
if(baru.voiceChannelID === channelid || !baru.voiceChannelID === Role || Role !== null && Role !== '') {
console.log(baru.displayName + ' gabisabgo hrus ada rank ranked ');
// const Role = baru.guild.roles.get("724997095236304987");
baru.guild
.createChannel(`${Role.name} | ${baru.user.username}`,"voice")
.then(tempChannel => {
tempChannel.overwritePermissions(baru.guild.defaultRole.id, {
CONNECT: false,
})
tempChannel.overwritePermissions(Role.id, {
CONNECT: true
})
tempChannel.setParent(kategorikanal);
baru.setVoiceChannel(tempChannel.id);
tempChannel.setUserLimit("5");
})
.catch(console.error)
}
if(lama.voiceChannelID || !lama.voiceChannelID === Role || Role !== null && Role !== '') {
console.log(lama.displayName + ' gabisabgo hrus ada rank ranked ');
const voicelama = lama.guild.channels.get(lama.voiceChannelID);
let Role = baru.roles.find((r) => ["IRON", "BRONZE"].includes(r.name));
if(voicelama.name.startsWith(`${Role.name} | ${baru.user.username}`)){
let sawadikap = `**${baru.user.username}'s**` + " **Team**"
var koko = new Discord.RichEmbed()
.setColor("#FF4654")
.setThumbnail(`${baru.user.avatarURL}`)
.addField('**Good Game Well Played**',`${sawadikap}`)
.setFooter("#Valorant Indonesia Community." , 'https://i.imgur.com/yPWqxxu.png')
voicelama.delete()
.then(function() {
music.channels.get('725080861392896101').send(koko)
})
.catch(console.error);
}
}
})
ERROR VIEW
.createChannel(${Role.name} | ${baru.user.username},"voice")
^ TypeError: Cannot read property 'name' of null
Have you stepped through the code in debug mode? I recommend setting breakpoints, creating watches, and checking the value of the variables as you step through. If you don't feel comfortable doing so, can you please put in the following, and tell me what the console logs? :
console.log(Role)
console.log(Role.name)
Although Role is not null, The value of Role.name is null, meaning that it has no value assigned to it. That issue occurs here:
let Role = baru.roles.find((r) => ["IRON", "BRONZE"].includes(r.name));
So I see two possibilities:
No roles contain those names.
I thought that find should only result one result, but I can't seem to find good documentation of that method. Is it possible that both roles are found and a collection is returned? This would mean that there would be a collection of multiple roles, meaning that Role would not contain the data members that a Role object type would. This means that you would have to index one of the roles before using the name.
//
//if there isn't a matching role, then terminate the method.
if (Role == null)
{
return;
}
//if there are multiple roles that match the criterion, just use the first one.
//The alternative is that we could make it into a loop that handles it for all of them.
else if (Role instanceof Array)
{
if (Role.length == 0)
{
return;
}
Role = Role[0]
}
Add the above lines before calling baru.guild.createChannel.
trying to find a way to condense this. wasnt sure of the best way to do it. basically if criteria is met i display an alert with a parameter that is the message. i was thinking of maybe trying it in function. this is part of a larger function react component. i was also thinking if i could find a way to condense the else if's i could use a ternary. thanks in advance for the assistance.
const handleUpdatePassword = () => {
const allFilled = !reject(passwords).length;
const passwordsMatch = newPassword === conPassword;
const isDifferent = curPassword !== newPassword;
const meetsPasswordRequirements = validatePassword();
const usesName = isUsingName();
const usesUserID = isPartOfUserID();
const isValidPassword = meetsPasswordRequirements && isDifferent;
if (allFilled) {
if (!isDifferent) {
Alert.alert(difPassWord);
} else if (!passwordsMatch) {
Alert.alert(noMatch);
} else if (!meetsPasswordRequirements) {
Alert.alert(pasReqs);
} else if (usesName || usesUserID) {
Alert.alert(pasName);
}
} else {
Alert.alert(fieldNotComplete);
}
if (isValidPassword) {
changePasswordPost(
{
userId,
curPassword,
newPassword
},
partyId
);
}
};
You can create an array of objects for your validation rules, each containing a function which returns a boolean indicating whether that validation passes, and a string with the error message to display.
Then loop over the rules array and alert the message for the first rule that returns false. If they all return true, do the post.
You can split each if statement into a function, then chain them. For example
// here we make a closure to validate, and return a Promise
// condition can be a function
const validate = (condition, error) => ()=> new Promise((res, rej)=>{
if(condition()){
res();
}else{
rej(error);
}
});
const handleUpdatePassword = () => {
const validateFieldsComplete = validate(
()=>!reject(passwords).length,
fieldNotComplete
);
const validateDifPassword = validate(
()=> curPassword !== newPassword,
difPassWord
);
// ...
validateFieldsComplete()
.then(validateDifPassword)
.then(...)
.catch(Alert.alert)
}
It would be much cleaner with pipe. You can take a look at ramda. Or if you are intrested in functional way, you might consider using Monad.
I'd recommend DRYing up the Alert.alert part since all branches have that in common, and just come up with an expression that evaluates to the alert message. Compactness isn't always everything, but if you want it, then nested conditional operators can fit the bill. I'm also rearranging your conditions so that it can be a flat chain of if/elses:
const message
= reject(passwords).length ? fieldNotComplete
: curPassword === newPassword ? difPassWord
: newPassword !== conPassword ? noMatch
: !validatePassword() ? pasReqs
: (isUsingName() || isPartOfUserID()) ? pasName
: null;
const isValid = !message;
if (!isValid) {
Alert.alert(message);
}
(feel free to use any other sort of code formatting pattern; nested conditionals always look awkward no matter which pattern you use, IMO.)
Edit:
Also inlined conditionals which will short-circuit evaluation and make it even more compact.
I'd setup a validations object that has the tests and error messages and then loop over it. If validation fails, it'll throw the last validation error message. Using this method, you only have to maintain your tests in one place and not mess with a block of conditional statements.
const handleUpdatePassword = () => {
const validations = {
allFilled: {
test() {
return newPass && oldPass
},
error: 'Must fill out all fields'
},
correct: {
test() {
return curPass === oldPass
},
error: 'Incorrect password'
},
[...]
}
const invalid = () => {
let flag = false
for (let validation in validations) {
if (!validations[validation].test()) {
flag = validations[validation].error
}
}
return flag
}
if (invalid()) {
Alert.alert(invalid())
} else {
changePasswordPost(
{
userId,
curPass,
newPass
},
partyId
)
}
}
hi everyone this was the method i used for a solution
const messages = [
{
alertMessage: difPassWord,
displayRule: different()
},
{
alertMessage: noMatch,
displayRule: match()
},
{
alertMessage: pasReqs,
displayRule: validatePassword()
},
{
alertMessage: pasName,
displayRule: !isUsingName() || !isPartOfUserID()
}
];
if (allFilled) {
const arrayLength = messages.length;
for (let i = 0; i < arrayLength; i++) {
if (messages[i].displayRule === false) {
Alert.alert(messages[i].alertMessage);
}
}