javascript - Correct way to reference children in reactjs -
i looking facebook's react.js , found cool far. tried make simple folder sturcture, can open , close each folder. structure looks this
<folder>
<header/>
<content/>
</folder>
clicking on header results in folder hiding/showing content. done via state.
but want have multiple folders , 'toggle all' button. how button toggle children without creating big clutter? used refs address them, think bad practice the documentation states:
...your first inclination going to try use refs "make things happen" in app...
...think state should owned in component hierarchy. often, becomes clear proper place "own" state @ higher level in hierarchy.
i created fiddle demonstrate whole thing. working don't think that's solution.
ps (bonus question): better hide content not rendering (like done in fiddle), or add 'display : none;' styletag?
correct way reference children in reactjs -> not reference childrens query state. if need query state parent, put state in parent , inject state props in children.
here code reworked: http://jsfiddle.net/t5fwn/7/
/** @jsx react.dom */ var initialstate = { "folders": [ { "name": "folder1", "open": false, "files": [{ "text": "content1 1" }] }, { "name": "folder2", "open": false, "files": [{ "text": "content2 1" }, { "text": "content2 2" }] } ] }; var folder = react.createclass({ render: function() { var items = []; if( this.props.folderdata.open ){ this.props.folderdata.files.foreach(function(file) { items.push( <div classname="itembox">{file.text}</div>); }); } return ( <div classname="items_directory"> <div classname="folder_header" onclick={this.props.onfolderclick}>{this.props.folderdata.name}</div> <div classname="folder_content"> {items} </div> </div> ); } }); var foldersmanager = react.createclass({ getinitialstate: function() { return this.props.initialstate; }, render: function(){ var self = this; var foldercomponents = this.state.folders.map(function(folder,folderindex) { var onfolderclick = function() { self.togglefolder(folderindex); }; return <folder folderdata={folder} onfolderclick={onfolderclick}/>; }); return ( <div> <button onclick={this.toggleall}>toggle all</button> <div> {foldercomponents} </div> </div> ); }, togglefolder: function(folderindex) { var newstate = this.state; newstate.folders[folderindex].open = !newstate.folders[folderindex].open; this.setstate(newstate); }, toggleall: function(){ var newstate = this.state; var newopentoset = this.isallfoldersopen() ? false : true; newstate.folders.foreach(function(folder) { folder.open = newopentoset; }); this.setstate(newstate); }, isallfoldersopen: function() { return this.countfoldersopen() == this.state.folders.length; }, countfoldersopen: function() { var = 0; this.state.folders.foreach(function(folder) { if ( folder.open ) i++; }); return i; } }); react.rendercomponent(<foldersmanager initialstate={initialstate} />, document.body);
it better have kind of manager component handle state open/close of folders. folder component used render folder not manage state of folder, or in global toggleall
operation have "query" child components know state.
ps (bonus question): think more elegant not render content not displayed. performance reasons, if hide/show state changes frequently, may better use display : none;
: produce same visual effect dom diff lighter. not optimize unless see performance problem not rendering hidden elements.
Comments
Post a Comment