0
setTimeout(() => this.setState({ messageSent: true }), 2000);

In the state initially messageSent: false, and I just want this text to appear for 2 seconds. Instead, what it does is completely the opposite: it appears after 2 seconds (and forever). Why?

{this.state.messageSent ? (
    <span className="message-sent">
        Your message has been sent. We will get back to you soon. Thank you for contacting us!
    </span>
) : null}
2
  • Hey David, you are setting the wrong state value in timeout. Please set it to false so that the condition render null. Commented May 7, 2020 at 12:43
  • You code sets it to true at two seconds. You code says "when true" show the span. So it works as expected. So if you want it to be the opposite, you change your logic the other way around..... Commented May 7, 2020 at 13:14

6 Answers 6

2

Try this:

this.setState({ showSentMessage: true }, () => {
    setTimeout(() => this.setState({ showSentMessage: false }), 2000);
})

rendeer Code

{
    this.state.showSentMessage ? (
        <span className="message-sent">
            Your message has been sent. We will get back to you soon. Thank you for contacting us!
    </span>
    ) : null
}
Sign up to request clarification or add additional context in comments.

Comments

1

Your code won't work because the setState is being called after the timeOut.

Here is the logic that you after:

setState(messageSent) -> true
wait 2000ms
setState(messageSent) -> false

You can add a call back at the end of your setState as follow:

this.setState({ messageSent: true }, () => { 
     setTimeout(() => this.setState({ messageSent: false }), 2000);
});

Has been answered by: https://stackoverflow.com/a/61658196/5653540

I just added a little bit of explanation. (new users can't add an extra comment) =(

Comments

0

You need to invert the logic - currently, since you're setting messageSent to true after 2000ms, this.state.messageSent ? ( jsx ) : null enters the jsx branch after 2000ms.

It'll probably be clearer if you change the property to something like showSentMessage, which starts out true, then set it to false after 2000ms:

setTimeout(() => this.setState({ showSentMessage: false }), 2000);
{this.state.showSentMessage? (
    <span className="message-sent">
        Your message has been sent. We will get back to you soon. Thank you for contacting us!
    </span>
) : null}

Comments

0

Reverse it and it should appear immediately and then hide after 2 seconds because of the timeout

!this.state.messageSent ? (
    <span className="message-sent">
        Your message has been sent. We will get back to you soon. Thank you for contacting us!
    </span>
) : null}

Comments

0

The below is easiest solution by using &&

!this.state.showSentMessage && (
    <span className="message-sent">
        Your message has been sent. We will get back to you soon. Thank you for contacting us!
    </span>
)

Comments

0

You need to work with state, Like loading for first time would be null. On submit, it will be true/loading. Once loaded, need to be false.

Or you can create a component like Toast and based on data you can play.

function Toast({open, message, autoClose, type = "info", timeout = 2000}) {
  const [status, setStatus] = useState(open);
  useEffect(() => {
    if(autoClose) {
      setTimeout(() => {
      setStatus(false);
    }, timeout);
    }
  }, []);
  return (
    <div>
      {status  ? (
        <span className={"message-sent" + " " +type}>
          {message}
        </span>
      ) : null}
    </div>
  )
}

See below example:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <title>Hello World</title>
  <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <style>
    .error {
      background-color: red;
    }
    .info {
      background-color: blue;
    }
  </style>
</head>

<body>
  <div id="root">Test</div>
  <script type="text/babel">
    const { createElement, useState, useEffect, useRef } = React;
function Toast({open, message, autoClose, type = "info", timeout = 2000}) {
  const [status, setStatus] = useState(open);
  useEffect(() => {
    if(autoClose) {
      setTimeout(() => {
      setStatus(false);
    }, timeout);
    }
  }, []);
  return (
    <div>
      {status  ? (
        <span className={"message-sent" + " " +type}>
          {message}
        </span>
      ) : null}
    </div>
  )
}
function Loader() {
  const [status, setStatus] = useState(null);
  useEffect(() => {
    setTimeout(() => {
      setStatus(false);
    }, 2000);
  }, [status]);
  const onSubmit = () => {
    setStatus(true);
  };
  return (
    <div>
      {status === true ? (
        <span className="message-sent">
          Your message has been sent. We will get back to you soon. Thank you
          for contacting us!
        </span>
      ) : null}
      <button onClick={onSubmit}>Click here to see message</button>
    </div>
  );
}
ReactDOM.render(<div>
  <Loader />
  <Toast open message={"Auto close message"} autoClose type="error" />
  <Toast open message={"info message"} autoClose timeout={4000}/>
  </div>, document.getElementById("root"));

</script>
</body>

</html>

Comments

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.