Skip to main content

Command Palette

Search for a command to run...

Hooking On React

Published
โ€ข4 min readโ€ขView as Markdown
A

Pre-final year student at NIT Kurukshetra ๐ŸŽ“ with a strong foundation in C, C++, Java, JavaScript, HTML, CSS, Node.js, and React ๐Ÿ’ป. Passionate about web development and deeply interested in AI and ML ๐Ÿค–. Eager to leverage my skills and knowledge to create innovative solutions and contribute to cutting-edge projects ๐Ÿš€.

I'm glad to share a mini-project that I made inorder to upskill myself in React.js. Check out my mini project at the link given below.

https://password-generator-zeta-lemon.vercel.app/

In this project I was able upskill myself by new and efficient learning about these following hooks that I didn't know before! You can read the about the following hooks (that I've explained in my own simplistic manner) and check out how I've used them in the project!

useCallback(): This hook memoizes any function that we want to based on certain dependencies (states/props). In React whenever a component is re-rendered, the functions declared inside that component are re-created! If this functions are passed to the children! Those children would have to be re-created as well! That's causes the child components to re-render unnecessarily which can cause your website to slow down! However if you wrap the function definition in useCallback(), your function would only be re-created if any of the dependencies change!

In this project I've used useCallback() to memoize the password Generator function, which is only re-created when either the length, numberAllowed, charAllowed and setPassword function changes! This makes the rendering more efficient!

useEffect: This is one the most common hooks in react and really easy to explain. It helps our system perform a certain "side-effect" whenever something on our page changes. For example, in this project, the useEffect hook regenerates the password whenever the variables length, number or character changes (as specified by the user!).

**Some certain things to keep in mind while specifying the dependencies in the useEffect() hook!

1) An empty dependency array means that the useEffect() will run only on the initial render.

2) Not specifying any dependency array means that the useEffect() will run on each re-render.

3) Specifying certain dependency will cause useEffect() to run on change of each dependency and intial render.

useRef(): This hook allows us to store information that is not used while rendering the UI. So why do we use it? Sometimes we just need to keep track of the information like "How many times has the user clicked this button?", we don't want to render the page again and again by using a useState(), to do this, we can use useRef() hook which contains "current" variable to keep track of such things. It is also used to keep reference of some HTML component and perform DOM manipulation!

In this project I've used it to hightlight the password whenever it is selected using the copy button by the user!

I was able to learn and write about these hooks by reading the React documentation at: https://react.dev/reference/react/hooks

A huge thanks to Hitesh Choudhary who helped me learn about these complex hooks through such a simple yet fruitful project.

I've provided the code below if anyone wants to check out:
You can also access the repo at: https://github.com/architChhajed06/passwordGenerator

import { useState, useCallback, useEffect, useRef } from 'react';
import './App.css';

function App() {
  const [length, setLength] = useState(8);
  const [numberAllowed, setNumberAllowed] = useState(false);
  const [charAllowed, setCharAllowed] = useState(false);
  const [password, setPassword] = useState('');
  const inputRef = useRef(null);

  const passwordGenerator = useCallback(() => {
    let pass = "";
    let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    if (numberAllowed) str += "0123456789";
    if (charAllowed) str += "!@#$%^&*()_+-=[]{}|;:',.<>/?~";

    for (let index = 0; index < length; index++) {
      let charIndex = Math.floor(Math.random() * str.length);
      let char = str.charAt(charIndex);
      pass += char;
    }

    setPassword(pass);
  }, [length, numberAllowed, charAllowed]);

  const copyToClipboard = () => {
    window.navigator.clipboard.writeText(password);
    inputRef.current?.select();
  };

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

  return (
    <div className="w-full max-w-md mx-auto p-6 bg-gray-800 rounded-lg shadow-lg md:max-w-lg lg:max-w-xl">
      <h1 className="text-3xl font-semibold text-white text-center mb-6">Password Generator</h1>

      <div className="flex flex-col sm:flex-row items-center mb-4 bg-gray-900 rounded-lg shadow-inner">
        <input 
          type="text"
          value={password}
          className="w-full py-2 px-4 text-lg text-gray-300 bg-gray-800 rounded-t-lg sm:rounded-l-lg sm:rounded-t-none focus:outline-none"
          placeholder="Generated password"
          readOnly
          ref={inputRef}
        />
        <button
          className="bg-blue-600 text-white px-4 py-2 rounded-b-lg sm:rounded-r-lg sm:rounded-b-none hover:bg-blue-500 transition-colors w-full sm:w-auto"
          onClick={copyToClipboard}
        >
          Copy
        </button>
      </div>

      <div className="flex flex-col gap-y-4">
        <div className="flex flex-col sm:flex-row items-center">
          <input
            type="range"
            min={6}
            max={100}
            value={length}
            className="w-full cursor-pointer accent-blue-600"
            onChange={(e) => setLength(parseInt(e.target.value))}
          />
          <span className="mt-2 sm:mt-0 sm:ml-4 text-gray-300">Length: {length}</span>
        </div>

        <div className="flex justify-between sm:justify-center sm:gap-x-8 text-gray-300 text-sm">
          <label className="flex items-center gap-x-2">
            <input
              type="checkbox"
              checked={numberAllowed}
              onChange={() => setNumberAllowed(prev => !prev)}
              className="accent-blue-600"
            />
            Numbers
          </label>
          <label className="flex items-center gap-x-2">
            <input
              type="checkbox"
              checked={charAllowed}
              onChange={() => setCharAllowed(prev => !prev)}
              className="accent-blue-600"
            />
            Characters
          </label>
        </div>
      </div>
    </div>
  );
}

export default App;