简体   繁体   中英

setInterval problem and useState doesn't change

I tried to count down the second and reload the page, the second showed in the component is correct but the printed on the console was always 5, so I couldn't reload. I want to count down and reload the page. Where do I put window.location.reload()? and why count always showed 5, but setCount is normal and decrease every second?

This is the code:

function Register() {
  const dispatch = useDispatch();

  const [count, setCount] = useState(5);

  const timeountToReload = () => {
    const interval = setInterval(() => {
      console.log(count); // always 5 here
      if (count === 0) {
        window.history.pushState({}, '', '/');
        window.location.reload();
      }
      setCount((count) => count - 1);
    }, 1000);

    return () => clearInterval(interval);
  };

  const handleRegister = async (e, value) => {
    e.preventDefault();
    setSuccessful(false);
    setFormControlDisable(true);

    await dispatch(register({ username, email, password }))
      .then(unwrapResult)
      .then((result) => {
        setSuccessful(true);
        timeountToReload();
      })
      .catch((error) => {});

    setFormControlDisable(false);
  };
  return (
    <Container style={{ marginTop: '15%' }}>
      <Row className='justify-content-md-center'>
        <Col md={{ span: 4, offset: 0 }} style={{ border: 'green solid 5px' }}>
          {count}
          <RegisterForm
            handleUsernameChange={handleUsernameChange}
            handlePasswordChange={handlePasswordChange}
            handleComfirmedPasswordChange={handleComfirmedPasswordChange}
            handleEmailChange={handleEmailChange}
            handleRegister={handleRegister}
            username={username}
            password={password}
            comfirmedPassword={comfirmedPassword}
            email={email}
            errors={errors}
            message={message}
            successful={successful}
            count={count} // component shows normal and refresh every second
            formControlDisable={formControlDisable}
          />
        </Col>
      </Row>
    </Container>
  );
}

export default Register;

I think that inside the interval you passed a function instead of a value to the setCount. try to replace

setCount(count => count - 1)

with

setCount(count - 1)

Try to keep track of count changes using the useEffect hook:

  const timeountToReload = () => {
    const interval = setInterval(() => {
      setCount((count) => count - 1);
    }, 1000);

    return () => clearInterval(interval);
  };

  useEffect(() => {
    console.log(count);
    if (count === 0) {
      window.location.reload();
    }
  }, [count]);

Link to playground.

you should use useEffect with the count as dependency to watch its chages, because inside setInterval it won't update

useEffect(() => {
  if (count === 0) {
    window.history.pushState({}, '', '/');
    window.location.reload();
  };
}, [count]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM