Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CSS Transitions in React

CSS Transitions in React

This is kind of a tutorial which shows how to implement CSS transition in React by your own.
Afterwards it's more clear what ReactTransitionGroup and ReactCSSTransitionGroup are doing in React.

Anton Wilhelm

October 12, 2015
Tweet

More Decks by Anton Wilhelm

Other Decks in Technology

Transcript

  1. Flux Flux is an application design paradigm used as a

    replacement for MVC. Pioneered by Jing Chen at Facebook. Flux is an application design paradigm used as a replacement for the more traditional MVC pattern. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code. Popular implementations of the Flux pattern Flux (Facebooks implementation) Reflux Fluxxor Fluxible Flummox Alt http://stackoverflow.com/tags/flux/info
  2. State Redux Store Actions State Component A Component B Component

    C Reducer React Component props state render() {}
  3. A few notes on React Component changed by owner which

    triggers a new render pass can be set by the component itself props state render() {}
  4. ECMAScript 2015 CSS .example-enter { opacity: 0.01; } .example-enter.example-enter-active {

    opacity: 1; transition: opacity 500ms ease-in; } .example-leave { opacity: 1; } .example-leave.example-leave-active { opacity: 0.01; transition: opacity 300ms ease-in; } WTF WTF render() { return ( <div> <button onClick={this.handleAdd}>Add Item</button> <ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} > {items} </ReactCSSTransitionGroup> </div> ); } }
  5. HTML <section> <div class="fade"> </div> </section> CSS .fade { width:200px;

    height:200px; transition:all 0.5s ease; background:blue; }
  6. HTML <section> <div class="fade"> </div> </section> CSS .fade { width:200px;

    height:200px; transition:all 0.5s ease; background:blue; }
  7. HTML <section> <div class="fade"> </div> </section> CSS .fade { width:200px;

    height:200px; transition:all 0.5s ease; background:blue; } .fade:hover { background:red; }
  8. HTML <section> <div class="fade"> </div> </section> CSS .fade { width:200px;

    height:200px; transition:all 0.5s ease; background:blue; } .fade:hover { background:red; }
  9. HTML <section> <div class="fade"> </div> </section> CSS .fade { width:200px;

    height:200px; transition:all 0.5s ease; background:blue; } .fade:hover { background:red; }
  10. HTML <section> <div class="fade"> </div> </section> CSS .fade { width:200px;

    height:200px; transition:all 0.5s ease; background:blue; } .fade:hover { background:red; } create a react component
  11. HTML <section></section> CSS .fade { width:200px; height:200px; transition:all 0.5s ease;

    background:blue; } .fade:hover { background:red; } ECMAScript 2015 class Box extends React.Component { render() { return <div className={'fade'}></div> } } React.render(<Box />, document.querySelector("section"));
  12. CSS .fade { width:200px; height:200px; transition:all 0.5s ease; background:blue; }

    .fade.fade-enter { background:red; } ECMAScript 2015 class Box extends React.Component { render() { return ( <div> <button>toggle</button> <div className={'fade'}></div> </div> ) } } add button
  13. CSS .fade { width:200px; height:200px; transition:all 0.5s ease; background:blue; }

    .fade.fade-enter { background:red; } ECMAScript 2015 class Box extends React.Component { render() { return ( <div> <button onClick={() => {this.toggleFade();}}>toggle</button> <div className={'fade'}></div> </div> ) } } add click handler
  14. CSS .fade { width:200px; height:200px; transition:all 0.5s ease; background:blue; }

    .fade.fade-enter { background:red; } ECMAScript 2015 class Box extends React.Component { render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div> <button onClick={() => {this.toggleFade();}}>toggle</button> <div className={className}></div> </div> ) } } set CSS class names
  15. CSS .fade { width:200px; height:200px; transition:all 0.5s ease; background:blue; }

    .fade.fade-enter { background:red; } ECMAScript 2015 class Box extends React.Component { toggleFade() { this.setState({fade: !this.state.fade}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div> <button onClick={() => {this.toggleFade();}}>toggle</button> <div className={className}></div> </div> ) } } toggle state
  16. CSS .fade { width:200px; height:200px; transition:all 0.5s ease; background:blue; }

    .fade.fade-enter { background:red; } ECMAScript 2015 class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } toggleFade() { this.setState({fade: !this.state.fade}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div> <button onClick={() => {this.toggleFade();}}>toggle</button> <div className={className}></div> </div> ) } } initial state
  17. CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display:

    inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  18. ECMAScript 2015 CSS class Box extends React.Component { constructor() {

    super(); this.state = {fade: false}; } componentDidMount() { this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className}> </div> ); } } toggle after mounting .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  19. ECMAScript 2015 CSS class Box extends React.Component { constructor() {

    super(); this.state = {fade: false}; } componentDidMount() { this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className}> </div> ); } } toggle after mounting .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  20. ECMAScript 2015 CSS class Box extends React.Component { constructor() {

    super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className}> </div> ); } } .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  21. ECMAScript 2015 CSS class Box extends React.Component { constructor() {

    super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className}> </div> ); } } undefined .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  22. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } } CSS string or callback .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  23. ECMAScript 2015 class App extends React.Component { constructor() { super();

    } render() { return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  24. ECMAScript 2015 class App extends React.Component { constructor() { super();

    } render() { return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS let’s create a state for the items .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  25. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } render() { return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  26. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } render() { return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS let’s create Box components .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  27. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  28. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS add click handler .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  29. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  30. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS immutable .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  31. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  32. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  33. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  34. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box key={item}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } CSS class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } } .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  35. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box key={item}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } class Box extends React.Component { constructor() { super(); this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } } CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  36. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box key={item}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } }
  37. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box key={item}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } add clickhandler
  38. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map(function(item) { return <Box key={item} removeItem={() => {this.delBox(item)}}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } }
  39. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map((item) => { return <Box key={item} removeItem={() => {this.delBox(item)}}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } fix `this` context of map loop
  40. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } render() { let boxItems = this.state.items.map((item) => { return <Box key={item} removeItem={() => {this.delBox(item)}}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } add function
  41. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } delBox(item) { let items = this.state.items; let index = items.indexOf(item); items.splice(index, 1); this.setState({items: items}); } render() { let boxItems = this.state.items.map((item) => { return <Box key={item} removeItem={() => {this.delBox(item)}}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } }
  42. ECMAScript 2015 class App extends React.Component { constructor() { super();

    this.state = {items: [], counter: 0}; } addBox() { this.setState({ items: this.state.items.concat([++this.state.counter]) }); } delBox(item) { let items = this.state.items; let index = items.indexOf(item); if (index === -1) {return} items.splice(index, 1); this.setState({items: items}); } render() { let boxItems = this.state.items.map((item) => { return <Box key={item} removeItem={() => {this.delBox(item)}}>{item}</Box> }); return ( <div> <button onClick={() => {this.addBox();}}>new</button> <div className='container'>{boxItems}</div> </div> ); } } handle multiple clicks
  43. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } }
  44. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref}> </div> ); } } add click handler
  45. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} ></div> ); } }
  46. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} ></div> ); } } add content <Box key={item} removeItem={() => {this.delBox(item)}}>{item}</Box>
  47. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } }
  48. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } } add function
  49. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { this.setState({fade: false}); this.props.removeItem(); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } }
  50. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { this.setState({fade: false}); this.props.removeItem(); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } } transition starts but at the same time the element is unmounted
  51. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { this.setState({fade: false}); window.getComputedStyle(this.element).opacity; this.props.removeItem(); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } }
  52. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { this.setState({fade: false}); window.getComputedStyle(this.element).opacity; this.props.removeItem(); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } } no effect
  53. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { setTimeout(this.props.removeItem, 5000); this.setState({fade: false}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } }
  54. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { setTimeout(this.props.removeItem, 5000); this.setState({fade: false}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } } works, but is ugly CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  55. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { setTimeout(this.props.removeItem, 2000); this.setState({fade: false}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } } https://developer.mozilla.org/ en-US/docs/Web/Events/transitionend
  56. ECMAScript 2015 class Box extends React.Component { constructor() { super();

    this.state = {fade: false}; } componentDidMount() { window.getComputedStyle(this.element).opacity; this.setState({fade: true}); } fadeOutAndRemove() { this.element.addEventListener("transitionend", () => { this.props.removeItem(); }); this.setState({fade: false}); } render() { let className = 'fade' + (this.state.fade ? ' fade-enter' : ''); return ( <div className={className} ref={(ref) => this.element = ref} onClick={() => {this.fadeOutAndRemove()}} >{this.props.children}</div> ); } }
  57. Vanilla JavaScript (ES5) var container = document.querySelector('.container'); var counter =

    0; document.querySelector('button').addEventListener('click', function(e) { var box = document.createElement("div"); box.className = "fade"; box.textContent = ++counter; container.appendChild(box); box.addEventListener('click', function(e) { var box = e.target; if (box.dataset.deleting == "true") {return} box.dataset.deleting = 'true'; // block multiple handlers box.classList.remove('fade-enter'); box.addEventListener('transitionend', function(e) { var box = e.target; box.parentElement.removeChild(box); }); }) window.getComputedStyle(box).opacity; box.classList.add('fade-enter'); }); HTML <section> <button>new</button> <div class="container"> </div> </section> CSS .fade { width:20px; height:20px; transition:all 5s ease; background:blue; display: inline-block; opacity:0; } .fade.fade-enter { opacity:1; }
  58. ECMAScript 2015 render() { return ( <div> <button onClick={this.handleAdd}>Add Item</button>

    <ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} > {items} </ReactCSSTransitionGroup> </div> ); } } CSS .example-enter { opacity: 0.01; } .example-enter.example-enter-active { opacity: 1; transition: opacity 500ms ease-in; } .example-leave { opacity: 1; } .example-leave.example-leave-active { opacity: 0.01; transition: opacity 300ms ease-in; }
  59. CSS inline styles <li name="js__planning-object" class="line"> <div class="entry po-type__task selected"

    style="padding-left: 7.93333em;"> <span data-pin-left="data-pin-left" class="pin left"></span> <time title="1" class="js__planning-object-time editMode compliant-date progressEmpty" draggable="true" style="width: 0.00833333em;"> <div class="progressBar" title="Vorgang zu 0 % erledigt." style="width: 0%;"></div> </time> <span data-pin-right="data-pin-right" class="pin right"></span> <span name="name" class="title">1</span> </div> </li>
  60. CSS inline styles <li name="js__planning-object" class="line"> <div class="entry po-type__task selected"

    style="padding-left: 7.93333em;"> <span data-pin-left="data-pin-left" class="pin left"></span> <time title="1" class="js__planning-object-time editMode compliant-date progressEmpty" draggable="true" style="width: 0.00833333em;"> <div class="progressBar" title="Vorgang zu 0 % erledigt." style="width: 0%;"></div> </time> <span data-pin-right="data-pin-right" class="pin right"></span> <span name="name" class="title">1</span> </div> </li>
  61. CSS inline styles Why? CSS .todoitem__is-visible {…} .todoitem__is-hidden {…} .todoitem__is-expanded

    {…} .todoitem__is-collapsed {…} .todoitem__is-in-work {…} .todoitem__is-ready-for-review {…} .todoitem__is-in-review {…} .todoitem__is-done {…}
  62. CSS inline styles in React - no pseudo classes -

    no pseudo elements - no media queries
  63. ECMAScript 2015 var Radium = require('radium'); var color = require('color');

    @Radium class Button extends React.Component { render() { return ( <button style={[styles.base]}>{this.props.children}</button> ); } } // You can create your style objects dynamically or share them for // every instance of the component. var styles = { base: { color: '#fff', background: '#0074D9' // Adding interactive state couldn't be easier! Add a special key to your // style object (:hover, :focus, :active, or @media) with the additional rules. ':hover': { background: color('#0074d9').lighten(0.2).hexString() } } }; // Enhance component with Radium RadiumButton = Radium(Button); // Render enhanced React component React.render(< RadiumButton/>, document.getElementById('root'));
  64. Transition examples • http://codepen.io/anon/pen/VvzZWr - CSS only hover transition •

    http://codepen.io/anon/pen/WQOVbE - React hover transition • http://codepen.io/anon/pen/jbLPBo - React button toggle • http://codepen.io/anon/pen/dYzYyj - React creating boxes • http://codepen.io/anon/pen/gaxaxY - VanillaJS creating boxes • http://codepen.io/anon/pen/EVvVmQ - React creating + deleting boxes • http://codepen.io/anon/pen/WQEQEx - VanillaJS creating + deleting boxes • http://codepen.io/anon/pen/dYzMBe - React official transition example • http://codepen.io/anon/pen/EVvKqv - React official transition example at initial mounting • http://codepen.io/kenwheeler/pen/PqWajd - React + Radium simple button example