0

I've trying to implement simple updates in a function component in react and seem to have stumbled onto some basic logical errors on my part. Can you help?

My code :

import React, { useState } from "react";
import "./App.css";

var timeout;  // this variable wasn't scoped inside the function?.

function App() {
  const [name, setUserName] = useState("");

  const [password, setUserPassword] = useState("");

  const [showHackMessage, setShowHackMessage] = useState(false);

  const enterUserName = e => {
    console.log(e.target.value);
    setUserName(e.target.value);
  };

  const enterUserPassword = (e) => {

    console.log(e.target.value,timeout);
    setUserPassword(e.target.value);
    if (e.target.value.length > 0) {
      timeout= setTimeout(()=>setShowHackMessage(true), 1000);
      console.log(timeout);

      /// Why did not  timeout= setTimeout(setShowHackMessage(true), 5000); work? is  setShowHackMessage not a function?
      //  timeout();
    } 
    else if(e.target.value.length===0) {
      console.log("Tricky user!");
      console.log(timeout,'L29>>');
      //not working perfectly!
      clearTimeout(timeout);
      setShowHackMessage(false);
    }
  };

  return (
    <div className="App">
      <p>Login-Hacker</p>
      <input name={"email"} onChange={enterUserName}></input>
      <br></br>
      <br></br>

      <input name={"password"} onChange={(e)=>enterUserPassword(e)}></input>
      <p>Powered by Saurabh</p>
      {name.length > 0 && <p>Your name is {name}</p>}
      {password.length > 0 && <p>Your password is {password}</p>}
      {showHackMessage && <p className='awesome'>Now you are hacked!</p>}
    </div>
  );
}

export default App;

So my first question would be:-

  1. Why do i have to use callback while defining a setstate function in settimeout? I tried

    timeout= setTimeout(setShowHackMessage(true), 1000); and it didn't work, while

    timeout= setTimeout(()=>setShowHackMessage(true), 1000); works perfectly. Is setShowHackMessage (in useState not a function?)

  2. If i define the variable var timeout inside the function, the cleartimeout doesn't work(shows as undefined in console), but works perfectly if i define it outside the function, as in the code. Is the whole function "rendered" after setstate( hence losing previous instance of variable timeout?).Should i have used refs for this?

    Thank you.

6
  • use useEffect for that ... 1) you already called func, not defined func to be called Commented Feb 15, 2020 at 13:35
  • First, describe what you want to achieve... Commented Feb 15, 2020 at 14:26
  • 1
    try using useRef() . useRef is used to mimic instance variables. Component doesnot rerender when it's value is changed Commented Feb 15, 2020 at 14:31
  • It seems useRef() is the way to go for holding the id of returned after setimeout. I don't see how useEffect would be helpful here though @xadm. Commented Feb 15, 2020 at 14:59
  • 1
    overreacted.io/making-setinterval-declarative-with-react-hooks - useEffect inside ;) Commented Feb 15, 2020 at 16:45

1 Answer 1

2

This is a simpler version. I removed the timeout variable as I don't see why you use it.

        import React, { useState, useCallback } from "react";
// import "./App.css";

// let timeout;  // this variable wasn't scoped inside the function?.
const EMPTY_STRING = "";

function App() {
const [name, setUserName] = useState("");
const [password, setUserPassword] = useState("");
const [showHackMessage, setShowHackMessage] = useState(false);
const [timer, setTimer] = useState(null);

const enterUserName = useCallback(
    value => {
    console.log(value);
    setUserName(value);
    },
    [setUserName]
);

const enterUserPassword = useCallback(
    value => {
    setShowHackMessage(false);
    setUserPassword(value);
    console.log("password value", value);
    if (timer) {
        console.log("clear Timer=>", timer);
        clearTimeout(timer);
    }
    if (value !== EMPTY_STRING) {
        setTimer(setTimeout(() => setShowHackMessage(true), 5000));
        console.log("set Timer=>", timer);
    }
    console.log("password", password);
    },
    [setUserPassword, setShowHackMessage, password, timer]
);

return (
    <div className="App">
    <p>Login-Hacker</p>
    <input
        name={"email"}
        value={name}
        onChange={e => enterUserName(e.target.value)}
    />
    <br />
    <br />

    <input
        name={"password"}
        value={password}
        onChange={e => enterUserPassword(e.target.value)}
    />
    <p>Powered by Saurabh</p>
    {name.length > 0 && <p>Your name is {name}</p>}
    {password.length > 0 && <p>Your password is {password}</p>}
    {showHackMessage && <p className="awesome">Now you are hacked!</p>}
    </div>
);
}

export default App;

Edit affectionate-jennings-htolo

Sign up to request clarification or add additional context in comments.

3 Comments

I am really sorry for not stating the purpose of using settimeout . I wanted to show the message "You are hacked", after an interval of 5 second of entering the password(so the setstate should have occured 5 seconds after the password was typed, and timeout should've cleared if user erased the password before 5 seconds). Sorry if the code seems funny, i was experimenting it was best i could come up with at the time. Thanks.
@SaurabhAgrawal I understand now. I updated the code !
useEffect should be used for clearing interval on unmount

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.