Created
November 24, 2016 10:40
-
-
Save dedan/c68db3aa798ba96e285bdd11fafb9556 to your computer and use it in GitHub Desktop.
FadeInFadeOut
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('normalize.css/normalize.css'); | |
require('styles/App.css'); | |
import React from 'react'; | |
const ObjectOne = () => { | |
return <div style={{width: 100, height: 100, backgroundColor: 'red'}} /> | |
} | |
const ObjectTwo = () => { | |
return <div style={{width: 100, height: 100, backgroundColor: 'green'}} /> | |
} | |
class FadeInFadeOut extends React.Component { | |
static propTypes = { | |
children: React.PropTypes.element, | |
transitionDurationMillisec: React.PropTypes.number, | |
} | |
static defaultProps = { | |
transitionDurationMillisec: 800, | |
} | |
constructor(props) { | |
super(props) | |
this.state = { | |
isFadingIn: false, | |
isFadingOut: false, | |
isInTransition: false, | |
nodeShown: props.children, | |
} | |
// The state will be modified like this during a transition: | |
// isFadingIn isFadingOut nodeShown | |
// false false 1 | |
// false true 1 | |
// ... | |
// true false 2 | |
// false false 2 | |
// ... | |
// end | |
} | |
componentWillReceiveProps(nextProps) { | |
if (nextProps.children.key === this.props.children.key) { | |
return | |
} | |
if (this.timeout) { | |
clearTimeout(this.timeout) | |
} | |
this.setState({ | |
isInTransition: true, | |
nextNode: nextProps.children, | |
}, this.startFadingOut) | |
} | |
startFadingOut = () => { | |
this.setState({isFadingOut: true}) | |
this.timeout = setTimeout(this.startFadingIn, this.props.transitionDurationMillisec / 2) | |
} | |
startFadingIn = () => { | |
this.setState({ | |
isFadingIn: true, | |
isFadingOut: false, | |
nodeShown: this.state.nextNode, | |
}, this.endFadingIn) | |
} | |
endFadingIn = () => { | |
this.setState({ | |
isFadingIn: false, | |
nextNode: null, | |
}) | |
this.timeout = setTimeout(this.endTransition, this.props.transitionDurationMillisec / 2) | |
} | |
endTransition = () => { | |
this.setState({isInTransition: false}) | |
} | |
componentWillUnmount() { | |
if (this.timeout) { | |
clearTimeout(this.timeout) | |
} | |
} | |
render() { | |
const {isFadingIn, isFadingOut, nodeShown} = this.state | |
const scale = isFadingOut || isFadingIn ? 0 : 1 | |
const style = { | |
opacity: isFadingOut || isFadingIn ? 0 : 1, | |
transform: `scale(${scale}, ${scale})`, | |
transformOrigin: '50px 50px', | |
transition: `ease-in ${this.props.transitionDurationMillisec / 2}ms`, | |
} | |
return <div style={style}> | |
{nodeShown} | |
</div> | |
} | |
} | |
class AppComponent extends React.Component { | |
state = { | |
isFirstShown: true, | |
} | |
componentDidMount = () => { | |
setTimeout(() => this.setState({isFirstShown: false}), 2000) | |
} | |
render() { | |
const {isFirstShown} = this.state | |
return ( | |
<div className="index"> | |
<FadeInFadeOut> | |
{isFirstShown ? <ObjectOne key='thing1' /> : <ObjectTwo key='thing2' />} | |
</FadeInFadeOut> | |
</div> | |
); | |
} | |
} | |
AppComponent.defaultProps = { | |
}; | |
export default AppComponent; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment