Reputation: 409
I am trying to make a application in react for rendering a tree like structure which can be expanded and collapsed on user input, although i have managed to get the app working as I want but the performance is quite slow. I am not sure if this is because of the nature of the application, the react component or my ignorance of the framework.
I have done a chrome profiling and here are the screenshots:
Please if you can help me understand through this images what is the bottleneck and if/how it can be solved.
Source :
https://github.com/harsh-a1/react-skeleton/tree/tree
Component :
export function TreeComponent(props){
var instance = Object.create(React.Component.prototype)
var state = {
previousSelected :{},
onSelectCallback : props.onSelectCallback
}
instance.props = props;
var toggle = function(){
instance.setState(state.data)
}
instance.updateState = function(){
instance.setState(Object.assign({},state))
}
if (!props.data){
init(function(ous){
state.data = ous;
instance.setState(state)
});
}
instance.render = function(){
if (!state.data){return <div key = "dummy"></div>}
return <ul key={"ul_"+state.data.id}>
<Tree data={state.data} updateState={instance.updateState} state={state } />
</ul>
}
return instance;
function Tree(props){
var instance = Object.create(React.PureComponent.prototype)
instance.render = function(){
if (!props.data.children || props.data.children.length == 0){
return (
<li key={"li_"+props.data.id}>
<LeafNode data={props.data} updateState = {props.updateState} state={props.state} />
</li>
)
}
return (
<li key={"li_"+props.data.id}><LeafNode data={props.data} updateState = {props.updateState} state={props.state} />
<ul key = {"ul_"+props.data.id} style={props.data.showChildren?{"display":"inline"}:{"display":"none"}}>
{
props.data.children.map(function(child){
return <Tree data={child} key={"tree_"+child.id} updateState = {props.updateState} state={props.state} />
})
}
</ul></li>
)
}
return instance;
function LeafNode(props){
var instance = Object.create(React.PureComponent.prototype)
instance.props = props;
/* instance.shouldComponentUpdate = function(nextProps) {
return (nextProps.data.showChildren !== this.props.data.showChildren);
}
*/
instance.componentDidMount= function(){
console.log("yes")
}
instance.toggle = function(){
props.data.showChildren = !props.data.showChildren;
props.updateState();
}
instance.selected = function(){
props.state.previousSelected.selected = false;
props.data.selected = !props.data.selected;
props.state.previousSelected = props.data;
props.updateState();
props.state.onSelectCallback(Object.assign({},props.data));
}
instance.render = function(){
var toggleImg = "";
if ( props.data.children.length!=0){
toggleImg = props.data.showChildren ?expandIMG:collapseIMG;
}
return (
<div key={"div_"+props.data.id} >
<span key={"span_"+props.data.id} className="toggle" >
<img key={"img_"+props.data.id} width="12" height="12" src={toggleImg} onClick={instance.toggle} />
</span>
<a key={"a_"+props.data.id} onClick = {instance.selected} style={props.data.selected? {color:"yellow"}:{color:"black"}} >{props.data.name}</a>
</div>
)
}
return instance
}
}
}
Thanks
harsh
Upvotes: 0
Views: 5381
Reputation: 10219
Here is an example with 1M+ nodes and good performance. The trick is to use local state and not render the hidden elements.
https://codesandbox.io/s/z6jr6zww4l
Upvotes: 1
Reputation: 409
Turns out The issue was that I was using the "development" build to check it....i switched to a production library and now it is running not to bad...still not as good as direct DOM but pretty close...although don't know how much it can scale...
Upvotes: 0
Reputation: 2174
Have a look at best practices how to create components and component lifecycle at React
website. It is a good idea to follow them so it would be easier to identify problems later.
It is also worth looking at react-virtualized components. There are a bunch of components that could be reused including list, grid, tree etc. Also look at their implementation since it is opensource.
Their virtual list component resolved my issue with rendering 500+ items.
Upvotes: 1