Hooking On React
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;