Sweet HOCs: withEnterTransition

Mitch Masia
hexient-labs
Published in
2 min readApr 24, 2018

A super simple Higher-Order Component to add a mounting transition to any component.

If you’ve ever wanted to create a cute mounting animation to delight your users, we’ve got a great solution for you. Our solution today will use React-Pose by Popmotion in conjunction with Recompose and Ramda to create a HOC that implements an animation.

Let’s dive in!

// withEnterTransition.jsimport React from 'react'
import PropTypes from 'prop-types'
import { omit } from 'ramda'
import { compose, lifecycle, setPropTypes, withStateHandlers } from 'recompose'
import posed from 'react-pose'
// Declare separate animation states
const poseProps = {
hidden: {
y: 10,
opacity: 0,
},
visible: {
y: 0,
opacity: 1,
}
}
// Create animated wrapper
const PosedContainer = posed.div(poseProps)
// Component with Animation
const withEnterTransition = BaseComponent => props => {
const baseProps = omit(['delay', 'poseState'], props)
return (
<PosedContainer pose={props.poseState}>
<BaseComponent {...baseProps} />
</PosedContainer>
)
}
// Create props and prop change handlers to manage Pose State
const withState = withStateHandlers(
({ poseState = 'hidden' }) => ({
poseState,
}),
{
updatePose: ({ poseState }) => (nextPoseState) => ({
poseState: nextPoseState
}),
}
)
// When the component mounts, after a timeout, update Pose state
const withLifecycle = lifecycle({
componentDidMount() {
setTimeout(() => {
this.props.updatePose('visible')
}, this.props.delay || 500)
}
})
// Declare PropTypes
const withPropTypes = setPropTypes({
delay: PropTypes.number,
})
export default compose(
withState,
withLifecycle,
withPropTypes,
withEnterTransition
)

Okay… I know that was intense. But if we break it down piece by piece, it starts to make sense.

First, to understand this example, you fundamentally have to understand how the React-Pose by Popmotion library works. All we have to do to trigger an animation is change the pose props on the PosedContainer to one of the designated states, and a transition will fire.

In this case, we change the opacity and y-position from (0, 10) to (1, 0), respectively.

Second, we create our own composed functionality called withState that creates some local state and a local state change handler for updating the poseState of a given component. We will soon apply this component to the PoseContainer and lifecycle hooks.

Third, we create our own lifecycle hooks and use the componentDidMount lifecycle method to trigger an animation after a specific timeout (the delay prop).

Fourth, we enhance our base component with the necessary delay PropType.

Lastly, we compose all our HOCs together to apply them to a base component!

Using Our HOC

It’s actually super straightforward.

// Example.jsimport React from 'react'
import { compose } from 'recompose'
import withEnterTransition from './withEnterTransition'
const Example = props => <h1>{props.title}</h1>export default compose(withEnterTransition)(Example)

Kaboom!

Now when we use the <Example delay={1000} title="Hello, world!" /> component in the rest of our code, the component will fade in and up after a delay of 1s.

--

--

Mitch Masia
hexient-labs

Mitch is a developer, teacher, and entrepreneur building cool things at Guaranteed Rate.