Things don’t just appear on the phone screen out of the blue. Showing the user how the UI elements fit together, where they come from, and where they go, is the cornerstone of a great user experience.

You may already know that animating the appearance of something can be straightforward. But what about when something needs to be hidden? If the component is already unmounted, how do you even animate its disappearance?

Seems… impossible, right?

But then, how does everyone have that? And not just everyone, but how can you make something like this?

How components are shown conditionally

Typically, to have a component either shown or hidden, depending on some state variable, we use expressions like this:

{ showRectView && < RectView />}

But we don’t want this component just to appear, we want to fade it in.

First shot at animating

Now that you want to somehow animate its appearance and disappearance, you could create a Fade component that would run the appearance animation, and use it like this:

{ showRectView && < Fade >< RectView /></ Fade >}

The thing is, it would not animate on unmount — because once showRectView is false , Fade will be unmounted too, and will not have a chance to animate the view out.

What we want is the way to keep rendering RectView until the animation has finished. And the Fade component is the best place to handle that.

A different approach

Instead of conditionally rendering, we can pass a visible=true/false prop to Fade , and let it animate its children on both appearance and disappearance. The Fade component itself can be rendered at all times:

< Fade visible = { showRectView } > < RectView /> < / Fade >

Fade implementation

The simplest Fade could be implemented using these building blocks of React Native animations:

Need for change: we want its children to change opacity from 0 to 1, and scale from 1.1 to 1.0 when appearing; and the other way around when disappearing.

Visual state: our visual state will be the visibility of its children, which runs from 0 (hidden) to 1 (visible).

Transitions: this can be anything. We can use the simplest one, timing .

. The pixels: we will map the 0-1 visibility value into opacity between 0 and 1, and transform’s scale between 1.1 and 1.0.

Want a handy little PDF to help you recall the building blocks? You can download the cheatsheet below. Otherwise keep reading.

Exclusive bonus: Download the free Building blocks of React Native animations cheatsheet that you can print out or have handy on your desktop.

I'll email it to you right away so you can access it from anywhere! Get the cheatsheet! No spam. I will occasionally send you my posts about JavaScript and React.

Article continues:

import { Animated } from 'react-native' ; class Fade extends Component { componentWillMount () { this . _visibility = new Animated . Value ( this . props . visible ? 1 : 0 ); } componentWillReceiveProps ( nextProps ) { Animated . timing ( this . _visibility , { toValue : nextProps . visible ? 1 : 0 , duration : 300 , }); } render () { const { visible , style , children , ... rest } = this . props ; const containerStyle = { opacity : this . _visibility . interpolate ({ inputRange : [ 0 , 1 ], outputRange : [ 0 , 1 ], }), transform : [ { scale : this . _visibility . interpolate ({ inputRange : [ 0 , 1 ], outputRange : [ 1.1 , 1 ], }), }, ], }; const combinedStyle = [ containerStyle , style ]; return ( < Animated . View style= { combinedStyle } { ... rest } > { children } </ Animated . View > ); } }

Which is awesome already!

The thing is, it keeps rendering children with opacity = 0 even when visible=false . But we don’t want that, of course.

One idea might be to render anything when this.props.visible is true , but this still has the drawbacks of the conditional rendering solution.

Instead, we need to be able to unmount the children after the animation has finished running.

To get there, we can keep a state property, called, quite uncreatively, visible . We will change it as follows:

when the visible prop becomes true , set the visible in the state to true immediately.

prop becomes , set the in the state to immediately. when the visible prop becomes false , set the visible in the state to false after the animation has finished.

constructor ( props ) { super ( props ); this . state = { visible : props . visible , }; }; componentWillReceiveProps ( nextProps ) { if ( nextProps . visible ) { this . setState ({ visible : true }); } Animated . timing ( this . _visibility , { toValue : nextProps . visible ? 1 : 0 , duration : 300 , }). start (() => { this . setState ({ visible : nextProps . visible }); }); }

And now, you can get a nice appearance and disappearance animation by wrapping a component into:

// determine whether to show, possible based on state const visible = ... < Fade visible = { visible } > < SomeComponent /> < / Fade >

The full source of the Fade component would be: