Day 6 of  75 learning Dev

Day 6 of 75 learning Dev

Password Generator project

In this project we want something like that ,

So , In this project we can generate the password based on our required length , if we change the length the password will change , similary we can add number inside the password this automatically generate the new password ,similary for characters .Extra thing i have added is that you can copy the password with copy button.

import { useCallback, useEffect, useState } from 'react';

function App() {
  const [length, setLength] = useState(8);
  const [numberAllowed, setNumberAllowed] = useState(false);
  const [characterAllowed, setCharacterAllowed] = useState(false);
  const [password, setPassword] = useState('');

  const passwordGenerator = useCallback(() => {
    let pass = '';
    let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    if (numberAllowed) {
      str += '0123456789';
    }
    if (characterAllowed) {
      str += '~!@#$%^&*()_±={}|[]:';
    }

    for (let i = 1; i <= length; i++) {
      let char = Math.floor(Math.random() * str.length + 1);
      pass += str.charAt(char);
    }
     setPassword(pass);
  }, [length, numberAllowed, characterAllowed]);

  const handleCopy = () => {
    navigator.clipboard.writeText(password);
  }; 

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

  return (
    <>
      <div className="flex justify-center items-center min-h-screen bg-gray-100">
        <div className="w-2/4 p-6 bg-white rounded-lg shadow-md">
          <h1 className="text-3xl font-bold mb-4 text-center">Password Generator</h1>
          <div className="flex mb-4">
            <input
              type="text"
              value={password}
              className="border rounded px-4 py-2 w-full mr-2"
              placeholder="Password"
              readOnly
            />
            <button
              className="bg-blue-500 text-white px-4 py-2 rounded"
              onClick={handleCopy}
            >
              Copy
            </button>
          </div>
          <div className="mb-4">
            <input
              type="range"
              value={length}
              min={6}
              max={100}
              onChange={(e) => setLength(e.target.value)}
              className="w-full"
            />
            <label className="block">Length: {length}</label>
            <input
              type="checkbox"
              defaultChecked={numberAllowed}
              onChange={() => setNumberAllowed((prev)=>!prev)}
              className="mr-2"
            />
            <label className="mr-4">Numbers</label>
            <input
              type="checkbox"
              defaultChecked={characterAllowed}
              onChange={() => setCharacterAllowed((prev)=>!prev)}
              className="mr-2"
            />
            <label>Characters</label>
          </div>
        </div>
      </div>
    </>
  );
}

export default App;

Step wise explanation :

  • So you can see there are 4 useState used that are length , number , character, and password .

  • These all are changing that’s why we used as hook so that they can update themselves.

HOOK - useCallback

useCallback is a hook provided by React that memoizes a callback function, which means it returns a memoized version of the callback function that only changes if one of the dependencies has changed.

In the above code:

  • passwordGenerator is a memoized callback function. It's a function responsible for generating a password based on certain conditions.

  • Inside the function, it initializes two variables pass and str. pass will hold the generated password, and str contains the characters from which the password will be generated.

  • Depending on the state of numberAllowed and characterAllowed, it appends additional characters to str.

  • Then it enters a loop from 1 to the desired length of the password. In each iteration, it generates a random character from the str and appends it to pass.

  • Finally, it sets the generated password using setPassword.

  • The useCallback hook is used here to prevent unnecessary re-renders of the component caused by the passwordGenerator function. It will only recreate the function when one of its dependencies (length, numberAllowed, characterAllowed) changes. This optimization can be helpful in certain scenarios to improve performance.

HOOK - useEffect

  • useEffect is a hook provided by React that allows you to perform side effects in function components. Side effects can include things like data fetching, subscriptions, or manually changing the DOM.

  • It takes two arguments: a function and an optional dependency array.

  • The function passed to useEffect will run after every render by default. However, you can specify dependencies in the dependency array so that the effect will only run if any of those dependencies have changed.

  • If you provide an empty dependency array, the effect will only run once, similar to componentDidMount in class components.

  • If you return a cleanup function from the function passed to useEffect, it will be executed before the effect runs again or when the component unmounts.

    Note , In this basically i want to say that the first default call will go for setPassword so that password generate and visible in input box after that when any change will occur in the dependencies that we have provided then this useEffect will call otherwise not this save us to call for infinite times .

If we not use useEffect and directly call only passwordGenerator() then it will call for infinte times.

In summary, useEffect is for managing side effects, while useCallback is for optimizing the performance of functions by memoizing them.

Handle copy

handleCopy is a simple function that copies the generated password to the clipboard when invoked. It uses the navigator.clipboard.writeText() method to write the password to the clipboard.

Another code without useCallback

import { useEffect, useState } from 'react';

function App() {
  const [length, setLength] = useState(8);
  const [numberAllowed, setNumberAllowed] = useState(false);
  const [characterAllowed, setCharacterAllowed] = useState(false);
  const [password, setPassword] = useState('');

  useEffect(() => {
    let pass = '';
    let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    if (numberAllowed) {
      str += '0123456789';
    }
    if (characterAllowed) {
      str += '~!@#$%^&*()_±={}|[]:';
    }

    for (let i = 1; i <= length; i++) {
      let char = Math.floor(Math.random() * str.length);
      pass += str.charAt(char);
    }
    setPassword(pass);
  }, [length, numberAllowed, characterAllowed]);

  const handleCopy = () => {
    navigator.clipboard.writeText(password);
  }; 

  return (
    <>
      <div className="flex justify-center items-center min-h-screen bg-gray-100">
        <div className="w-2/4 p-6 bg-white rounded-lg shadow-md">
          <h1 className="text-3xl font-bold mb-4 text-center">Password Generator</h1>
          <div className="flex mb-4">
            <input
              type="text"
              value={password}
              className="border rounded px-4 py-2 w-full mr-2"
              placeholder="Password"
              readOnly
            />
            <button
              className="bg-blue-500 text-white px-4 py-2 rounded"
              onClick={handleCopy}
            >
              Copy
            </button>
          </div>
          <div className="mb-4">
            <input
              type="range"
              value={length}
              min={6}
              max={100}
              onChange={(e) => setLength(e.target.value)}
              className="w-full"
            />
            <label className="block">Length: {length}</label>
            <input
              type="checkbox"
              defaultChecked={numberAllowed}
              onChange={() => setNumberAllowed((prev)=>!prev)}
              className="mr-2"
            />
            <label className="mr-4">Numbers</label>
            <input
              type="checkbox"
              defaultChecked={characterAllowed}
              onChange={() => setCharacterAllowed((prev)=>!prev)}
              className="mr-2"
            />
            <label>Characters</label>
          </div>
        </div>
      </div>
    </>
  );
}

export default App;

As here both hooks are doing same thing to save again and again from re-rendering so we used only useEffect.