React - useState only affecting last property value - javascript

I'm trying to set validPassword and validFormData values to false whenever a form is submited and the values are empty. I'm calling this function on submit but it's only changing the last property in my useState
const [validPassword, setValidPassword] = useState({
password: true,
confirmPassword: true
})
const [validFormData, setValidFormData] = useState({
email: true,
name: true,
lastName: true,
phone: true,
})
const signupAction = (e) => {
e.preventDefault()
if (formData.email === "" || formData.name === "" || formData.lastName === "" || formData.phone === "" || formData.password === "" || formData.confirmPassword === "") {
for (let p in formData) {
if (formData[p] === "") {
if (p === "password" || p === "confirmPassword") {
setValidPassword({ ...validPassword, [p]: false })
} else {
setValidFormData({ ...validFormData, [p]: false })
}
}
}
} else {
console.log('success')
}
/* signup(formData, history) */
}
What I get from this is:
validPassword = {
password: true,
confirmPassword: false
}
validFormData = {
email: true,
name: true,
lastName: true,
phone: false,
}

The setState function is async. The common pattern of setting a state which is the one you are using is not fool proof one. One should use callback based setting state to by pass these common issues. Code like below would work
const signupAction = (e) => {
e.preventDefault()
if (formData.email === "" || formData.name === "" || formData.lastName === "" || formData.phone === "" || formData.password === "" || formData.confirmPassword === "") {
for (let p in formData) {
if (formData[p] === "") {
if (p === "password" || p === "confirmPassword") {
setValidPassword((prevState) => ({...prevState, [p]: false }))
} else {
setValidFormData((prevState) => ({ ...prevState, [p]: false }))
}
}
}
} else {
console.log('success')
}
/* signup(formData, history) */
}
Further, to prevent multiple updates, it is best if you store the changes in the loop in a local variable and set all at once like below
const signupAction = (e) => {
e.preventDefault()
if (formData.email === "" || formData.name === "" || formData.lastName === "" || formData.phone === "" || formData.password === "" || formData.confirmPassword === "") {
const tempValidPassword = { ...validPassword};
const tempValidFormData = { ...validFormData};
for (let p in formData) {
if (formData[p] === "") {
if (p === "password" || p === "confirmPassword") {
tempValidPassword[p] = false;
} else {
tempValidFormData[p] = false;
}
}
}
setValidPassword(tempValidPassword);
setValidFormData(tempValidFormData);
} else {
console.log('success')
}
/* signup(formData, history) */
}
Note: These are only pesudo-code. Fit according to your needs. Try to use functional updates to state as mentioned here whenever possible

Related

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'emailAddress')

I am parsing a few emails from a CSV in the method below and i am getting Cannot read properties of undefined (reading 'emailAddress'). I even tried filtering the undefined results out but no luck . How can I filter the ones that are undefined.
const getContactsFromText = (text) => {
if(text == "" || text.trim() == '' || text === undefined){
settingTheAlert();
return;
}
const contacts = text.split(/[,;\n]/)
.filter(x => x.length > 0)
.map(x => x.trim())
.map(x => {
const [, , displayName = '', emailAddress = ''] = x.match(/"?((.*?)"?\s*<)?([^">]*)/);
if (!emailAddress && !displayName) return;
if(emailAddress === undefined) return;
return { id: emailAddress, emailAddress, displayName, isChecked: true };
})
.filter(x => isValidEmail(x.emailAddress))
.sort(sortByEmail);
if(contacts.length < 1){
settingTheAlert();
return;
}
onImport(contacts);
}
const isValidEmail = (email) => {
const EMAIL_RE = /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const isValid = EMAIL_RE.test(String(email).toLowerCase());
if (!isValid) console.log('invalidEmail', { email })
return isValid;
}
In your code here:
.map(x => {
const [, , displayName = '', emailAddress = ''] = x.match(/"?((.*?)"?\s*<)?([^">]*)/);
if (!emailAddress || !displayName) return;
if (emailAddress === undefined) return; // this is useless (it's covered above)
return { id: emailAddress, emailAddress, displayName, isChecked: true };
};
})
you implicitly return nothing/undefined on these lines:
if (!emailAddress || !displayName) return;
if (emailAddress === undefined) return; // again, this line is not needed
which is equivalent to returning undefined. Then in the subsequent filter you assume the x.emailAddress exists, but it might not, as just above you were returning undefined under some corner cases.
To remedy that you either:
Gotta change your filter function (probably the best solution)
Make the isValidEmail function expect the whole email object rather than the expected string (probably a bit less desirable)
If you got for the first approach, it should look something like:
// ... other code
.map(x => {
const [, , displayName = '', emailAddress = ''] = x.match(/"?((.*?)"?\s*<)?([^">]*)/)
if (!emailAddress || !displayName) {
return null
}
return { id: emailAddress, emailAddress, displayName, isChecked: true }
})
.filter(emailObj => emailObj && isValidEmail(emailObj.emailAddress)) // checking first that the emailObj is not undefined and then checking if the emailObj.emailAddress is valid.
Should work.

Cannot convert undefined or null to object or not length

If you put a value in every input, it works normally. However, errors appear even if only one input is empty.
nameValue.length, an error appears that you cannot work on the length.
Object.values(nameValue).length, the error 'Cannot convert undefined or null to object' appears.
const [values, setValues] = useState({
nameValue: '',
numberValue: '',
contentValue: '',
});
const { nameValue, numberValue, contentValue } = values;
const handleNumber = e => {
const { value, name } = e.target;
setValues({
...values,
[name]: value,
});
};
useEffect(() => {
if (numberValue.length === 11) {
setValues({
numberValue: numberValue.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'),
});
} else if (numberValue.length === 13) {
setValues({
numberValue: numberValue
.replace(/-/g, '')
.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'),
});
}
}, [numberValue]);
const handleSend = e => {
e.preventDefault();
//console.log(typeof stringify(nameValue) === 'undefined');
const nameValueTrue =
Object.values(nameValue).length > 4 ||
Object.values(nameValue).length < 1 ||
typeof nameValue !== 'string' ||
typeof nameValue === 'undefined';
const numberValueTrue =
Object.values(numberValue).length < 13 ||
Object.values(numberValue).length > 14;
const contentValueTrue =
typeof contentValue !== 'string' ||
Object.values(contentValue).length < 2;
const error = !e.target.value;
if (nameValueTrue) {
alert('이름을 확인해주세요.');
console.log('name안');
} else if (numberValueTrue) {
console.log('number');
alert('휴대폰번호를 확인해주세요.');
} else if (contentValueTrue) {
console.log('content');
alert('내용을 확인해주세요.');
} else {
goto();
}
};
<ContentBox>
<div>Name</div>
<ContentInput
name="nameValue"
value={nameValue || undefined}
//value={nameValue || ''}
//value={nameValue}
onChange={handleNumber}
/>
</ContentBox>
<ContentBox>
<div>Phone Number</div>
<ContentInput
name="numberValue"
value={numberValue || undefined}
//value={numberValue || ''}
//value={numberValue}
onChange={handleNumber}
/>
</ContentBox>
<ContentBox>
<div>Content</div>
<ContentInput
placeholder="내용 입력."
name="contentValue"
value={contentValue || undefined}
//value={contentValue || ''}
//value={contentValue}
onChange={handleNumber}
/>
</ContentBox>
<Submit onClick={handleSend}>Send</Submit>
In your useEffect, you're overwriting the whole values object to just be numberValue. You need to spread the object there too, like you have in handleNumber

How to delete a voice channel when everybody disconnects?

I created a join to create system that creates a channel when a user join and delete it when they leave. However, it only deletes if the last person that's leaving is the user who created the room. Any ideas?
const { Collection } = require("discord.js");
const voiceCollection = new Collection();
module.exports = async (Discord, client, oldState, newState) => {
const user = await client.users.fetch(newState.id);
const member = newState.guild.member(user);
// JOIN
if (!voiceName || voiceName === "") {
if (!oldState.channel && newState.channelID === "898245212541976667") {
const channel = await newState.guild.channels.create(user.tag, {
type: "voice",
parent: newState.channel.parent,
});
member.voice.setChannel(channel);
voiceCollection.set(user.id, channel.id);
await channel.overwritePermissions([
{
id: user.id,
allow: ["MANAGE_CHANNELS", "CONNECT"],
},
{
id: member.guild.id,
deny: ["CONNECT"],
},
]);
} else if (!newState.channel) {
if (oldState.channelID === voiceCollection.get(newState.id)) {
if (oldState.channel.members.size < 1) {
return oldState.channel.delete();
}
}
}
var newchannel_id = config.Channel_id;
var category_id = config.category;
var userchannellist = []
client.login(token);
client.on('voiceStateUpdate', async (oldMember, newMember) => {
if (newMember.channel !== null && oldMember.channel === null && newMember.channel.id === newchannel_id || newMember.channel !== null && oldMember.channel !== null && newMember.channel.id === newchannel_id) {
var current_user = newMember.member.user;
console.log(current_user.username + 'creating the channel');
// Start the creation of the new channel
var server = newMember.guild;
let USERA = newMember.member.nickname || newMember.member.user.username;
var channel = {
type: 'voice', bitrate: 384000, parent: category_id, permissionOverwrites: [{
// permissions
id: server.id, allow: ['VIEW_CHANNEL'],
},
{
id: current_user.id, allow: ['MOVE_MEMBERS', 'MANAGE_CHANNELS']
}
]
};
server.channels.create('🔊' + USERA, channel).then(channel => {
newMember.setChannel(channel).catch(console.error)
userchannellist.push(channel)
//channel region
client.api.channels(channel.id).patch({ data: { rtc_region: "rotterdam" } })
}).catch(console.error);
}
// delete Chaneel
if (oldMember.channel) {
let filter = (ch) =>
(ch.parentID == category_id)
&& (ch.id !== newchannel_id)
&& (oldMember.channel == ch.id)
&& (oldMember.channel.members.size == 0);
return oldMember.guild.channels.cache
.filter(filter)
.forEach((ch) => ch.delete()
.catch(console.error));
}
});

"something went wrong" error on fucntion getfloat

This code works perfectly beside the last part , and I do not see where might be the error. I tested it, and the main problem is in Trade.prototype.getFloat maybe is the callback idk, (the Trade.prototype.getFloat I got it from a 3y post here on stack from other user).
3y problem: This code works perfectly besides this line: "inventory[asset.assetid].floatvalue = getFloat". As you can see it is situated in async mode, and this line initializes a request to get some value, but it cant get it couse value is undefined. I tested it, and the main problem in request, which is asynchronous too. So the answer is how to stop the async mode and wait the return of the request.
'use strict'
const config = require('../config')
const request = require('request')
const async = require('async')
const Trade = require('./index')
const MAX_RETRIES = 3
const API_URL = 'https://api.steamapis.com/steam/inventory'
Trade.prototype.getInventory = function getInventory(steamID64, appID, contextID, callback, retries) {
request(`${API_URL}/${steamID64}/${appID}/${contextID}?api_key=${config.SteamApisKey}`, (error, response, body) => {
if (!error && response.statusCode === 200) {
const items = JSON.parse(body)
const assets = items.assets
const descriptions = items.descriptions
const inventory = {}
if (descriptions && assets) {
async.forEach(descriptions, (description, cbDesc) => async.forEach(assets, (asset, cbAsset) => {
if (
description.classid !== asset.classid ||
!description.tradable ||
!description.marketable ||
description.market_hash_name.indexOf('Souvenir') > -1
) {
return cbAsset()
}
if (typeof inventory[asset.assetid] !== 'undefined') {
return cbAsset()
}
const type = Trade.prototype.getItemType(description.market_hash_name, description.type)
const wear = Trade.prototype.getItemWear(description.market_hash_name)
const inspect = Trade.prototype.getInspect(steamID64, asset.assetid, description.actions)
const getFloat = Trade.prototype.getFloat(inspect, asset.assetid, function(_float){
var data = String(_float);
inventory[asset.assetid].floatvalue = data;
inventory[asset.assetid] = asset
inventory[asset.assetid].item_type = type
inventory[asset.assetid].item_wear = wear
inventory[asset.assetid].inspect = inspect
inventory[asset.assetid].data = {
background: description.background_color,
image: description.icon_url,
tradable: description.tradable,
marketable: description.marketable,
market_hash_name: description.market_hash_name,
type: description.type,
color: description.name_color,
};
return cbAsset();
})
}));
}
return callback(null, inventory)
}
let retry = retries
if (typeof retries === 'undefined') {
retry = 0
}
retry += 1
if (retry <= MAX_RETRIES) {
return Trade.prototype.getInventory(steamID64, appID, contextID, callback, retry)
}
let statusCode = null
if (typeof response !== 'undefined' && typeof response.statusCode !== 'undefined') {
statusCode = response.statusCode
}
return callback({ error, statusCode })
})
}
Trade.prototype.getInventories = function getInventories(params, callback) {
const inventories = {}
async.each(params, (user, cb) => {
Trade.prototype.getInventory(user.steamID64, user.appID, user.contextID, (err, data) => {
inventories[user.id] = {}
inventories[user.id] = {
error: err,
items: (!err) ? Object.keys(data).map(key => data[key]) : null,
}
cb()
})
}, () => {
callback(inventories)
})
}
Trade.prototype.getItemType = function getItemType(marketHashName, type) {
if (marketHashName.indexOf('Key') !== -1) {
return { value: 0, name: 'key' }
}
if (marketHashName.indexOf('★') !== -1) {
return { value: 1, name: 'knife' }
}
if (
type.indexOf('Classified') !== -1 ||
type.indexOf('Contraband') !== -1 ||
type.indexOf('Covert') !== -1
) {
return { value: 2, name: 'rare_skin' }
}
if (
type.indexOf('Consumer Grade') !== -1 ||
type.indexOf('Base Grade') !== -1 ||
type.indexOf('Graffiti') !== -1 ||
type.indexOf('Sticker') !== -1 ||
type.indexOf('Industrial Grade') !== -1
) {
return { value: 4, name: 'misc' }
}
return { value: 3, name: 'weapon' }
}
Trade.prototype.getItemWear = function getItemWear(marketHashName) {
if (marketHashName.indexOf('Factory New') !== -1) {
return 'FN'
}
if (marketHashName.indexOf('Minimal Wear') !== -1) {
return 'MW'
}
if (marketHashName.indexOf('Field-Tested') !== -1) {
return 'FT'
}
if (marketHashName.indexOf('Well-Worn') !== -1) {
return 'WW'
}
if (marketHashName.indexOf('Battle-Scarred') !== -1) {
return 'BS'
}
return false
}
Trade.prototype.getInspect = function getInspect (steamID64, assetid, actions) {
let inspectLink = null;
if (actions) {
for (const a in actions) {
if (actions[a].name.indexOf('Inspect') !== -1) {
inspectLink = actions[a].link
inspectLink = inspectLink.replace('%owner_steamid%', steamID64)
inspectLink = inspectLink.replace('%assetid%', assetid)
}
}
}
return inspectLink
}
Trade.prototype.getFloat = function getFloat (adding, callback) {
request ("https://api.csgofloat.com:1738/?url=" + adding, (error, response, body) => {
if (!error && response.statusCode == 200) {
var floatBody = JSON.parse(body);
var float = floatBody["iteminfo"]["floatvalue"];
var id = id;
if (float != "") {
callback(float);
} else {
return "wrong";
}
} else {
console.log('something goes wrong');
return "wrong";
}
});
}

Searching For Nested Object in Angular

I have a problem searching for a nested array in my Angular app. I have to access the package.name. Please help thanksenfoiewfhfofhfowfoewhfowfoewhfwefwfhowefweofhew8ofwofhewofw8eofhwf
JSON
[{
"id": 1,
"name": "Yeah",
"package_id": 1,
"price": 100,
"package": {
"id": 1,
"name": "Yeah"
}
}]
TS
search(event) {
const val = event.target.value.toLowerCase();
if (!val) {
this.users = this.tempUsers;
}
const temp = this.tempUsers.filter((row) => {
return Object.keys(row).some((property) => {
return row[property] === null ? null : row[property].toString().toLowerCase().indexOf(val) !== -1;
});
});
this.users = temp;
}
TS
getAllUsers() {
this.usersService.getAll()
.subscribe(
(data: any) => {
console.log(data);
this.users = data.Users;
this.tempUsers= [...this.users];
},
error => {
console.log(error);
});
}
Does this work for you,
const temp = this.tempUsers.filter((row) => {
return Object.keys(row).some((property) => {
if (property === 'package') {
// check package.name value here
// like return row[property].name === 'something' ? true : false;
} else {
// the rest of the outer properties can be checked here
// not modifying your code here, but make sure it works for you
return row[property] === null ? null : row[property].toString().toLowerCase().indexOf(val) !== -1;
}
});
});
I have only answered your question on how to access the nested object inside the array method. Hope it helps or gives you an idea to fine tune your solution.
According to your data, You can use the following filter;
const filteredData = data.filter((item) => item.price.toString() === val || item.package_id.toString() === val || item.package.name.toString().toLowerCase().indexOf(val) !== -1 );
// UPDATED WITH CODE
search(event) {
const val = event.target.value.toLowerCase();
const filteredData = this.users.filter((item) => item.price.toString() === val ||
item.package_id.toString() === val ||
item.package.name.toString().toLowerCase().indexOf(val) !== -1 );
this.users = filteredData ;
}

Categories

Resources