I'm trying to validate the phone field, to get all letters and dots with the code below.
validatePhone = () => {
const sanitizedPhone = this.state.phone.replace(/\D/g, '');
if (sanitizedPhone.length >= 10 && sanitizedPhone.length <= 11) {
this.setState({ phone: sanitizedPhone });
return true;
}
toast.error('Invalid phoneNumber.', {
position: "top-center",
autoClose: false,
closeOnClick: true,
});
return false;
}
When i trying console.log(sanitizedPhone) with dots in input like 11.97.4.4.51234 i get 11974451234 but after this, on console.log(this.state.phone) i get the older number 11.97.4.4.51234
From react docs:
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall.
This is why you don't see your change right after you're using setState.
Related
Using Mongoose hooks, I need that if the property called outstandingBalance has a value of zero, the status automatically changes to false.
Trying to do this using Mongoose's PRE hook works but only by re-invoking the request after outstandingBalance was already zero before. That is why I have decided to use the POST hook so that once the setting of outstandingBalance to zero is finished, it changes the property from statua to false.
This is the code that I use with PRE that works fine but is not really viable for what I need:
SaleSchema.pre('findOneAndUpdate', async function() {
const docToUpdate = await this.model.findOne(this.getQuery())
if (docToUpdate.outstandingBalance < 1) {
this._update.status = false;
}
})
So I decided to change PRE to POST but it never works:
SaleSchema.post('findOneAndUpdate', async function() {
const docToUpdate = await this.model.findOne(this.getQuery())
if (docToUpdate.outstandingBalance < 1) {
this._update.status = false;
}
})
'POST' means all done, there is no action after that(the data is already updated), you have to save it again after setting the status to update the status.
PRE hook is correct for your case, just change the condition: Checking on update data instead of current data
SaleSchema.pre('findOneAndUpdate', async function() {
const docToUpdate = await this.model.findOne(this.getQuery())
if (this._update.outstandingBalance < 1 || (!this._update.outstandingBalance && docToUpdate.outstandingBalance < 1)) {
this._update.status = false;
}
})
This was the solution to be able to set the status to false depending on the outstandingBalance value using the Pre hook:
SaleSchema.pre('findOneAndUpdate', function (next) {
if(this._update.$set.outstandingBalance < 1) {
this._update.status = false
}
next();
});
Many thanks to him for his help as #hoangdv guided me to find the solution.
I have created this function in react native:
confirmOTP(){
console.log(this.state.otpEntry)
console.log(this.state.sixDigitauth)
if (this.state.otpEntry === this.state.sixDigitauth){
this.setState({
modalVisibility: false
})
console.log ("authenticated")
}else{
console.log ("incorrect OTP")
}
}
Although the function console logs both this.state.otpEntry and this.state.sixDigitauth and the text in them matches, I still end up getting a console log of "incorrect OTP". This means that the if statement is unable to match both states.
464042 464042 incorrect OTP
Both data types are text:
this.state = { sixDigitauth: '', otpEntry: '', }
Any idea why?
thanks in advance
It appears like you have a mismatch of datatypes, and since a triple equal sign attempts to match variables on their content, as well as their type - it returns false, hence your query fails.
You have a couple of options:
Add a + sign in front of the variables. It will convert them to a Number type:
confirmOTP(){
if (+this.state.otpEntry === +this.state.sixDigitauth) {
// do something
} else {
// do something else
}
}
Replace a === sign, with == sign. I don't recommend it, but it will technically solve the problem.
confirmOTP(){
if (this.state.otpEntry == this.state.sixDigitauth) {
// do something
} else {
// do something else
}
}
You could also make sure they're in appropriate datatypes, at the moment of updating the state:
constructor(props) {
super(props)
this.state = {
otpEntry: +props.otpEntry
sixDigitauth: +props.sixDigitauth
}
}
Make sure to catch up on some theory.
equations:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
unary plus:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus
I have a password field on my Vue.JS form that should update a progress bar, the policy is quite simple, I have 5 conditions, each should add 20% to the progress bar. what I have done is 5 computed checks for each condition which looks something like this:
hasLower() {
return this.password == null
? null
: /[a-z]/.test(this.password);
}
thenI trigger a function at keyPress to count how many trues am I getting from the 5 checks and update the value of a counter that is later mapped to the progress bar, like this:
checkPassword() {
this.trueCounter = 0;
this.progressBar.value = 0;
if (this.hasLower) this.trueCounter++;
if (this.hasUpper) this.trueCounter++;
if (this.hasDigit) this.trueCounter++;
if (this.hasSChar) this.trueCounter++;
if (this.has8) this.trueCounter++;
console.log("Probe: " + this.trueCounter)
}
My problem is that values are updated by the following key press! For example, if I type "a" in the password field, I get 0, if I type it again I get a 1 and it stays like this. then if I type in a character that triggers a different condition "A" for example, I get the last value again and it's changed only by the following Key press.
Is there a way to overcome this one keypress delay so I can always get the updated value immedietly?
I would probably set that as a computed value so that it is updated every time the password is updated. Maybe something like below would work better for you?
new Vue({
data: {
password: ""
},
computed: {
hasLower: function() {
return this.password && /[a-z]/.test(this.password);
},
hasUpper: function() {
return this.password && /[A-Z]/.test(this.password);
},
hasDigit: function() {
return this.password && /[0-9]/.test(this.password);
},
hasSChar: function() {
return false; // User yours here. I don't know the regex off the tope of my head.
},
has8: function() {
return this.password && this.password.length >= 8;
},
password_strength: function() {
var points = 0;
if (this.hasLower) points++;
if (this.hasUpper) points++;
if (this.hasDigit) points++;
if (this.hasSChar) points++;
if (this.has8) points++;
return points;
}
}
});
EDIT: Just realized the original post does not have () at the end of those, so I added them. They may well be properties in your code, so no parentheses makes sense that way. I just made them methods.
EDIT2: I take that back, they'll probably be better off as computed properties. Taking a second look, it looks like I've got something very similar to what you have, but as far as I can tell, the password strength is calculated correctly on my end. When the password hits the appropriate checks, the password strength variable is updated appropriately.
//It's working now - updated code
I'm working on my own autocomplete component because I have problem with passing firebase data to a ready one.
The whole mechanism is working good but I have problem with passing values after getting user input
I'm setting initial state with those values
const INITIAL_STATE = {
allChars: [],
suggestions: [],
value: ""
};
Then in autocomplete class i'm loading all users from database
loadData(){
let self = this;
let characters = firebase.firestore().collection("users");
characters.get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
let document = doc.data();
self.setState(({allChars})=>({
allChars: [
...allChars,
document
]
}))
});
});
}
Here is my getSuggestions function. It is firing on input change
getSuggestions = event => {
const {value, suggestions} = event.target;
this.setState({
value: value,
suggestions: []
})
let suggest = [];
this.state.allChars.map((allChars) => {
if(value.length > 1 && allChars.name.toLowerCase().includes(value.toLowerCase())){
suggest.push (
allChars.name
);
}
})
this.setState({
suggestions: suggest
})
}
In render I just put {sugestions}
But in {suggestions} I get rendered only one name.
one
But when I console.log it - I get two names
two
There should be two.
I tried to set state in this function like in loadData(), but I still get only one value.
Is there other way to get both values into DOM
Full code can be found here: https://github.com/Ilierette/react-planner/blob/master/src/component/elements/Autocomplete.js
I think the reason you are just seeing one element each time your components re-render is that in your map function on your allChars array, when you want to update the suggestions in your state, you are setting just the name each time as a new array while you should update the existing array in your state, so your code should be:
this.setState({
suggestions: [...this.state.suggestions, allChars.name]
})
Our team is working on a webapp / game where we want to make an API call every 8 seconds if a condition is true.
This process is triggered by a button which starts the populate method
async autoLoad() {
const timer = await 8;
console.log('debug consolelog')
const result = await this.UpdateProfile();
}
togglePopulate() {
const status = this.state.autoLoad;
if (status === true) {
this.setState({ autoLoad: false });
} else {
this.setState({ autoLoad: true });
this.autoLoad();
}
}
Our understanding was that this would run the 'UpdateProfile()' function in the background every 8 seconds. The result, however, is that our entire webpage locks up and the UpdateProfile (or the debug console.log) is not run.
Does anyone have an idea what we are doing wrong? (Or if what we are attempting to do is even possible?)
No offense, but I think you may be misunderstanding how async await works if you are trying to set the timer via, const timer = await 8. You may want to read up on some articles that describe exactly what Async Await returns to you.
However, setting a function to be called on a timer is actually kind of confusing with React. I feel like this is more of the problem that you are having. I hope this example helps you.
class Example extends React.Component {
constructor(props) {
super(props)
this.state = {
interval: null
}
this.enableAutoload = this.enableAutoload.bind(this)
this.disableAutoload = this.disableAutoload.bind(this)
}
enableAutoload() {
const setTimer = window.setInterval(() => {
this.iRunEveryEightSeconds()
}, 8000)
this.setState({ interval: setTimer })
}
disableAutoload() {
console.log('Clearing the timer from state...')
const clearTimer = window.clearInterval(this.state.interval)
this.setState({ interval: clearTimer })
}
iRunEveryEightSeconds() {
console.log('Hello There.')
}
render() {
return (
<div className="example">
Example API Call Every 8 Seconds
<button onClick={this.enableAutoload} className="enable">
Enable Autoload
</button>
<button onClick={this.disableAutoload} className="disable">
Disable Autoload
</button>
</div>
)
}
}
ReactDOM.render (
<Example />,
document.querySelector('#app')
)
I know that you need to run this API call when a specific condition is met. You can use this example to see how to set the timer into state when the condition is true, and clear the interval in state when it evaluates to false. Make sure to check out the console in the Codepen example below after you click the enable button, and when you click the disable button. "Hello There" will stop being printed every 8 seconds after you click the disable button.
The included Codepen example, will help you out further. Any questions, please ask!