Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - how to wait and fade out?

Tags:

reactjs

I have an alert box to confirm that the user has successfully subscribed:

<div className="alert alert-success">
    <strong>Success!</strong> Thank you for subscribing!
</div>    

When a user sends an email, I'm changing the "subscribed" state to true.

What I want is to:

  • Show the alert box when the subscribed state is true
  • Wait for 2 seconds
  • Make it fade out

How can I do this?

like image 238
lumenwrites Avatar asked Mar 11 '17 10:03

lumenwrites


People also ask

How do you session timeout in React?

Set a timeout via setTimeout to set the active to false after 13 minutes of inactivity. Everytime the user moves the mouse / touches the screen, reset the timeout. In the main app component, you can do something similar to end a session.

How do you make a div appear slowly in React?

Just use a conditional class and CSS. Have a state variable like visible . So depending upon the state. visible the input will have a class of either fadeIn or fadeOut .

How do you wait for state change in React?

Use the useEffect hook to wait for state to update in React. You can add the state variables you want to track to the hook's dependencies array and the function you pass to useEffect will run every time the state variables change. Copied!


2 Answers

May 2021 update: as tolga and Alexey Nikonov correctly noted in their answers, it’s possible to give away control over how long the alert is being shown (in the original question, 2 seconds) to the transition-delay property and a smart component state management based on the transitionend DOM event. Also, hooks are these days recommended to handle component’s internal state, not setState. So I updated my answer a bit:

function App(props) {
  const [isShowingAlert, setShowingAlert] = React.useState(false);
  
  return (
      <div>
        <div
          className={`alert alert-success ${isShowingAlert ? 'alert-shown' : 'alert-hidden'}`}
          onTransitionEnd={() => setShowingAlert(false)}
        >
          <strong>Success!</strong> Thank you for subscribing!
        </div>
        <button onClick={() => setShowingAlert(true)}>
          Show alert
        </button>
        (and other children)
      </div>
    );
}

The delay is then specified in the alert-hidden class in CSS:

.alert-hidden {
  opacity: 0;
  transition: all 250ms linear 2s; // <- the last value defines transition-delay
}

The actual change of isShowingAlert is, in fact, near-instant: from false to true, then immediately from true to false. But because the transition to opacity: 0 is delayed by 2 seconds, the user sees the message for this duration.

Feel free to play around with Codepen with this example.


Since React renders data into DOM, you need to keep a variable that first has one value, and then another, so that the message is first shown and then hidden. You could remove the DOM element directly with jQuery's fadeOut, but manipulating DOM can cause problems.

So, the idea is, you have a certain property that can have one of two values. The closest implementation is a boolean. Since a message box is always in DOM, it's a child of some element. In React, an element is result of rendering a component, and so when you render a component, it can have as many children as you want. So you could add a message box to it.

Next, this component has to have a certain property that you can easily change and be completely sure that, as soon as you change it, the component gets re-rendered with new data. It's component state!

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      showingAlert: false
    };
  }
  
  handleClickShowAlert() {
    this.setState({
      showingAlert: true
    });
    
    setTimeout(() => {
      this.setState({
        showingAlert: false
      });
    }, 2000);
  }
  
  render() {
    return (
      <div>
        <div className={`alert alert-success ${this.state.showingAlert ? 'alert-shown' : 'alert-hidden'}`}>
          <strong>Success!</strong> Thank you for subscribing!
        </div>
        <button onClick={this.handleClickShowAlert.bind(this)}>
          Show alert
        </button>
        (and other children)
      </div>
    );
  }
}

Here, you can see that, for message box, either alert-shown or alert-hidden classname is set, depending on the value (truthiness) of showingAlert property of component state. You can then use transition CSS property to make hiding/showing appearance smooth.

So, instead of waiting for the user to click button to show the message box, you need to update component state on a certain event, obviously.

That should be good to start with. Next, try to play around with CSS transitions, display and height CSS properties of the message box, to see how it behaves and if the smooth transition happening in these cases.

Good luck!

PS. See a Codepen for that.

like image 138
rishat Avatar answered Nov 03 '22 12:11

rishat


The correct way is to use Transition handler for Fade-in/out

In ReactJS there is synthetic event to wait till fade-out is finished: onTransitionEnd.

NOTE there are different css effects associated with different handlers. Fade is a Transition not an Animation effect.

Here is my example:

const Backdrop = () => {
  const {isDropped, hideIt} = useContext(BackdropContext);
  const [isShown, setState] = useState(true);
  const removeItFromDOM = () => {
    debugger
    setState(false)
  };
  return isShown
    ? <div className={`modal-backdrop ${isDropped ? 'show' : ''} fade` } onClick={hideIt} onTransitionEnd={removeItFromDOM}/>
    : null
}
like image 43
Alexey Nikonov Avatar answered Nov 03 '22 11:11

Alexey Nikonov