Using useState, useCallback, useEffect and useRef to make a Password Generator in REACT

The best way to learn a concept in coding is to make a project around it. REACT hooks is a very important concept in the world of web development and therefore learning it becomes a necessity, not because everyone is learning it but it is super helpful when creating complex web application. The article will help you build a Password Generator using various React Hooks. There are some pre-requisites to building this password generator, you must know the basics of React JS (Components, props, JSX, file structure)

Understanding the Logic

The password generator we will be building takes different parameters like length, numbers and characters to generate a random password which is set of alphabets, numbers and characters. The user gets to set the length of password through a range selector, they can also choose if they want to have numbers or characters in a their password or not. We will also work on a "copy" button functionality which will allow the users to copy their password.

Now that we know about what we need to build, let's get a bit technical. The basic functionality of our program is to generate some random character with respect to the length user inputs, therefore we need to create some variables which will store alphabets, numbers and characters. We also need to create a function which generates a random index between 1 and the length of the string (of alphabets, and conditionally numbers or characters) and append the value of the index of the string to the password.

If this sounds a bit complex, let's straight away dive into our code.

Initializing the variables using the useState hook

While understanding the logic we might have got an idea that there are various variables which are changing their values very often. Let's now introduce our first REACT hook - useState, which allows us to have state variables in a functional component. It allows us to give the initial value of the variable and gives a setter function which can be called to change the initial value. It can be used like:

const [state, setState] = useState(initial value);

Here, state is the name of our variable, setState is the function which we call to change the default value and we pass the initial value inside useState(). The useState hook can hold any type of value including the primitive data types like string, integer, and Boolean, as well as complex data types such as array, object, and function.

Let's now come back to our Password Generator. Think about the variables which should to be initialized to make our job easier.

//Initializing the variables using useState hook
const [length, setLength] = useState(8);
const [numberAllowed, setNumberAllowed] = useState(false);
const [charAllowed, setCharAllowed] = useState(false);
const [password, setPassword] = useState("");

Above initialized 4 variables, let's talk about them one by one. We need a length variable to keep track of length which the user inputs. We have kept the default value of the length of the password 8, and we will trigger the setLength function whenever there is a change in the range selector.
We also initialized numberAllowed and charAllowed variables to know if the user wants numbers or characters in their password or not. We have initialized the variable with a boolean operator - false.
We created a password variable as well, which we initialized with an empty string. We can call the setPassword function once we are ready with our generated password.

Creating the main function

Let's now jump to the most interesting part of building this program, the core functionality. We basically need to create a function which returns a randomly generated password in accordance to length passed by the user and numbers or characters. What all do we need for creating this function?

  1. A string variable containing all the alphabets (in lower and upper case both).

  2. A variable for numbers and characters containing numbers and characters respectively, which we will append into the string variable on a condition.

  3. A loop to generate a random index from 1 to the length passed by the user and then append the value of the index into the password.

Having known all these we can easily create a function to generate a random password each time the user wants, but we see that this functionality require a lot of re-rendering of components which will lead to recreation of the function on every render. REACT limits the number of re-renders, and therefore to optimize our program let's introduce our second REACT hook - useCallback. useCallback hook memorizes the function, meaning it remembers the function between renders. So, if the dependencies (the things that could make the function change) haven't changed, React will return the same memoized function instead of creating a new one. It can be used like:

const memorizedFunction = useCallback(() => {
    //Function Body
}, [
//Dependencies
])

Here, memorizedFunction is the name of the variable which holds the memorized version of the function and useCallback is REACT hook which we are using. Dependencies is the an optional array which contains dependencies which if changed will lead to recreation of the function.

Coming back to our Password Generator, let's see how we use the above knowledge to create a function which returns a random password.

const generatePassword = useCallback(() => {
    let pass = ""; //generated password will be appended here
    let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqurstuvwxyz";
    if (numberAllowed) str += "0123456789";
    if (charAllowed) str += "~!@#$%^&*()-_{}|:<>?/.,';[]";

    //Loop for retrieving the str, num, char length times
    for (let i = 0; i < length; i++) {
      let char = Math.floor(Math.random() * str.length); //generates a random number b/w 1 to length of str
      pass += str.charAt(char); //appending a value from str to the pass string
    }
    setPassword(pass);
  }, [length, numberAllowed, charAllowed, setPassword]);

Given above, we've created a variable called generatePassword which holds our callback function whose dependcies are length, numberAllowed, charAllowed and setPassword. We have initialized a pass variable which contains an empty string (we'll later append the generated password here), and an str variable containing all the alphabets (in upper and lower case both). Then we created two conditional arguments numberAllowed and charAllowed which appends digits (from 0 to 9) and characters respectively into the str variable, if the state is true.

We then create a for loop which loops until i is greater than the length passed by the user, and adds 1 to i after every loop. Every time our loop loops a random index is generated between 1 to the length of our str variable, and the value of the index is passed into the pass variable. Once the loop is completed, we use the useState function of our password variable - setPassword() to change the initial value of password to our newly generated password i.e. pass.

Triggering or Calling the function

Now that we are mostly done with the logic part of our program, the only thing which is left is calling the function we made. Let's try simply calling it with our knowledge of JavaScript.

generatePassword()

Using this methodology we'll find an error in our console.

This is because the dependencies of our callback function are changing too frequently, causing the component to re-render continously. To tackle this issue, let's introduce our third and last React Hook for today - useEffect. useEffect is a hook which is used to perform side effects in function component. In our case, we are updating the DOM frequently and in React, the preferred way to handle UI updates is by changing state and letting React re-render the component based on that state change. useEffect can be used like:

useEffect(() => {
    //call the function here
}, [
    //Dependencies
])

The useEffect hook allows us to define the dependencies and therefore it'll only re-render once there is a change in the dependency i.e. it prevents re-rendering.

Let's now come back to our Password Generator and finish our program.

useEffect(() => {
    generatePassword();
}, [length, numberAllowed, charAllowed, setPassword]);

The code given above triggers the generatePassword function under a useEffect hook. By using useEffect with the dependency array containing length, numberAllowed, charAllowed, and setPassword, you're saying "call generatePassword() after the component renders initially and whenever any of these dependencies change." This ensures that the function is only called when it's needed, preventing unnecessary re-renders.

You can now easily write the JSX for the UI and use the logic which we created above.

You can also add a "Copy To Clipboard" functionality to enhance the look and feel of your program.

Conclusion

Through this article you learnt how to use different REACT Hooks (useState, useCallback and useEffect) in different scenarios to make our life easier as frontend developers. We learnt this while building a Password Generator which is good beginner level project to learn REACT, React Hooks and State Handling.

💡
The source code of this project is available on my GitHub profile. Click Here to check the repository.

Credits to Hitesh Choudhary for creating such an amazing course "**Complete React course with projects | part 1" and including this Password Generator project. Watch the video here