javascript - Juggling Animations and View Hierarchy in React -


i'm having frustrations react because view hierarchy ruining animations.

i have <layout> component setups tab-nav layout , children placed within content portion of layout. pure component has props title, settab, , currenttab.

if thinking view hierarchy perspective , one-directional data-flow, have layout child of each view view set title, current tab, , settab delegated parent.

this doing:

var = react.createclass({   proptypes: {     settab: react.proptypes.func.isrequired   },   render: function() {     return (       <layout title="a page" currenttab="a" settab={this.props.settab}>               </layout>                )   } }); 

now can use react router or tabs, right now, have simple top-level component switching tabs state:

var app = react.createclass({   getinitialstate: function() {     return {       currenttab: 'a'     }   },   settab: function(name) {     this.setstate({currenttab:name})   },   render: function() {     var component = false     if (this.state.currenttab == 'a') {       return <a settab={this.settab}/>     } else {       return <b settab={this.settab}/>     }   } }); 

this fine , dandy until want start adding animations.

in <layout> component, have highlight block want animate left right when switching between tabs.

        <div classname="tabbar">           <div classname={"highlight " + this.props.currenttab}></div>           <div classname="tabs">             <div classname="tab" onclick={() => {this.props.settab('a')}}>a</div>             <div classname="tab" onclick={() => {this.props.settab('b')}}>b</div>           </div>         </div> 

here's css animation:

.highlight {     border-bottom: 3px solid red;     width: 50%;     position: absolute;     top: 0;     bottom: 0;     transition: left .25s ease-in-out; } .highlight.a {     left: 0; } .highlight.b {     left: 50%; } 

i'm trying animate layout's title using react.addons.csstransitiongroup think issue same:

the problem here seems <layout> component entirely re-rendered each time because root of render tree (<a/> , <b/>) changing.

so question now, how invert view hierarchy <layout> doesnt keep getting re-rendered animation can work?

note: in less contrived example, layout may other props <a/> such onclick handlers.

here's jsfiddle demonstrating frustrations:

https://jsfiddle.net/ccorcos/3rupb0og/

ok. figured out works, i'm not sure if best practice i'd appreciate feedback before conclude answer.

i've come concept of stitch way of stitching functions through component hierarchy. allow me set state of parent component child component.

function stitch() {   return {     to: (f) => {       this.func = f     },     from: () => {       this.func.apply(null, arguments)     }   } } 

so <layout> looks this:

var layout = react.createclass({   proptypes: {     currenttab: react.proptypes.string.isrequired,     ontab: react.proptypes.func.isrequired,     stitchtitle: react.proptypes.string.isrequired   },   getinitialstate: function() {     return {       title: ''     }   },   componentwillmount: function() {     this.props.stitchtitle((title) => {       this.setstate({title})     })   },   // ... } 

and view looks this:

var = react.createclass({   proptypes: {     settitle: react.proptypes.func.isrequired   },   componentwillmount: function() {     this.props.settitle('page a')   },   //... } 

and have stitch them together.

var app = react.createclass({   getinitialstate: function() {     return {       currenttab: 'a'     }   },   settab: function(name) {     this.setstate({currenttab:name})   },   componentwillmount: function() {     this.titlestitch = stitch()   },   render: function() {     var view = false     if (this.state.currenttab == 'a') {       view = <a settitle={this.titlestitch.from}/>     } else {       view = <b settitle={this.titlestitch.from}/>     }     return (       <layout currenttab={this.state.currenttab} ontab={this.settab} stitchtitle={this.titlestitch.to}>         {view}       </layout>       )   } }); 

and sure enough works! here's jsfiddle:

https://jsfiddle.net/ccorcos/bltuldwh/


Comments