Simple looping proving to be difficult

I am currently making a password strength test for my portfolio. However, I am struggling with counting uppercase letters… I have got the regex for a string in which the user types in it detects a uppercase letter. When the regex returns true, I want the uppercase letters in the state to increment everytime it is true. However, I have set up a loop so every time it loops through and finds true for one letter, its always going to be true. It sounds complicated, So I have made a codepen for someone to look at and try and guide me round this problem. It probably is really simple…

This should work… https://codesandbox.io/s/sweet-architecture-47u5h?file=/src/App.js

So if you type in lowercase letters into here at first, its fine, and then type n uppercase letter, the console will say true however, it you then type lowercase letters from then on, it keeps adding one onto the uppercase state because every time it loops through the string, its going to be true for that letter…

Just to be clear, you are wanting it to show Uppercase: 4 for the following password?

abCdefGHiJkl

If so, you should not be putting the test for one or more uppercase letters inside a for loop. You will always be incrementing the uppercaseLetters property in state.

You have a few ways to accomplish:

  1. Iterate through the string (no need to create an array) and just increment uppercaseLetters when you find a character with an ASCII code in the range that represents A-Z.

  2. Match all the upper case letter (using the match method). If you use the correct flag you have learned here at FCC, you will create an array of all the uppercase letters in the string. Then it is just a matter of getting the length of that array for the count.

Would it be easier to just pass the last character (e.g. using slice) from value to handleUppercase.

BTW, I wouldn’t suggest starting the method name with handle unless it’s a handler.

when you say iterate through a string, isn’t a for loop one way to do this…?
Or use a forEach or something like that…?

oohhh, I didnt think of this…!
I shall give it a go, will have to go and remind myself of slice lol, been centuries since I have used it lol

Ok I have kind of got it working, However, when I console log the last letter its always a step behind

When I type ‘g’ in for example first, the console shows an empty string, and then when I type ‘J’ the console then shows ‘g’ for some reason

Can you update your Codesandbox so we can see your latest code?

Are you logging state or just a variable? If it’s the state you can use componentDidUpdate or the setState callback to log the state.

React docs: setState()

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. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied.

I think it has been updated, I have kind of got it working, problem is now, uppercase is always saying 1. I can see why, just trying to sort it now

Why do you need an array?

It gets redeclared every time the method runs so you can’t use its length like you are, not unless you move it out of the function. You also have to deal with when the user deletes a character (edit: so you don’t always just increment the state, but decrement it as well).

I don’t really think you need an array for this.

Ive got it!!! Finally, yeah, I figured an array was not the way to go at all. So now, I have got uppercase and lowercase, now onto the numbers lol…

1 Like

I have updated the codepen incase on the slight chance, anyone is experiencing the smae issues. Just noticed that numbers are being classed as uppercase characters…

Your updated code still has problems when characters are deleted from the input.

For example, if I type abcde and the backspace them out, it shows there are 9 Lowercase letters which is incorrect.

I still recommend using regex to count the lowercacase, uppercase, and numbers separately and then update state with one line (no need for all those if statements in your findSpecificCharacter method. I would also recommend changing the method name to findCharacterCounts, which is what the method is attempting to do.

  findCharacterCounts = (value) => {
    const numbersMatch = // use match method to capture all numbers
    const numbers = // get number of numbers based on previous line's result
    const lowerCaseMatch = // use match method to capture all lowercase letters
    const lowercaseLetters = // get number of lowercase letters based on previous line's result
    const upperCaseMatch = // use match method to capture all uppercase letters
    const uppercaseLetters = // get number of uppercase letters based on previous line's result
    this.setState({ numbers, lowercaseLetters, uppercaseLetters });
  };

I see what you mean… I cannot get this method to work. When I do any of the .matches and just console log the length, if I do not put that character in first, it breaks because it cannot do the length of null…

I could be really cheeky and just disable the backspace button and have a cross at the end so they can start over which would eliminate the characters being what they shouldn’t be…

What code are you trying? The regex is trivial. Getting the count from the match is a little less trivial, but something very doable.

Just trying to finalise my regex expressions, I am sure they will be the death of me…

You should probably review https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match to understand what the return values can be depending on the flag used.

Also, you might want to review the following challenge:

Here’s what I have got so far and only the lowercase is working…

const lowercaseMatch = value.match(/^[a-z]/g);
    console.log(lowercaseMatch);
    const numberMatch = value.match(/^[0-9]/g);
    console.log(numberMatch);
    const uppercaseMatch = value.match(/^[A-Z]/g);
    console.log(uppercaseMatch);

Why are you using the ^ in each regular expression?

I saw that all over the internet and now its working… Regex is going be my task over this weekenddd

I am right back where I was before but when I reload the app and type in any letter/number, I get:
TypeError: Cannot read property ‘length’ of null
I have updated the codepen if that helps