Reputation: 1151
I was messing around and creating a comment like tree structure, which works out fine except when I want to get into creating collapsing and expanding commenting trees. So far the display is well, it is displayed on my webpage in proper tree structure, just like reddit, however I want to build in a collapse and expand comments and subcomments feature. I have an idea of using jquery to appending a div as soon as it is finished rendering. What comes to mind when i think about it is:
var childDiv = "#" + comment._id;
var parentDiv = "#" + comment.pComment;
$(parentDiv).append(childDiv);
This is my idea of appending divs together, where pComment holds the parentComments id, and I already establish my divs with the id of themselves as soon as they are mapped/rendered. However the issue is how do I tell my render function this is what I want to do at the end of each render mapping. I map a comment at a time, and I create the div there, so obviously it cant map to that div if it isnt there, and this is where I get lost. I tried out the idea with making it a onclick function and worked out great, but I would like for it to append on each mapping, and at the end of it after the div is rendered, so it appends the div's in correct order. I think there's alot of differents way to go about this but I'm not sure how.
render : function() {
return(
<div>
<ul className = "list-unstyled">
{
this.props.comments.map(function(comment) {
return(
//Right here is what I want to append to another div.
<div id = {comment._id}>
<div className = "userComments">
//content
</div>
</div>
)
})
}
</ul>
</div>
)
}
Generally my goal is to create a parent div, and append to it any div that holds its children.
I've tried doing var x = $(parentDiv).append(childDiv);
and then I proceeded to call {x} in between the div so it would append it. For the parent case, pComment is defaulted to the id ROOT, every comment that is owned by that comment after has its 'pComment' value held by its owners id.
However doing so I get
Uncaught Error: Invariant Violation: traverseAllChildren(...): Encountered an invalid child; DOM elements are not valid children of React components.
Upvotes: 4
Views: 1256
Reputation: 3311
You should not imperatively modify the DOM with React. Call this.setState
and allow React to modify the DOM.
Keep an object representing your comment structure near the top of your component hierarchy, when something change that would need to modify it, you can call this.setState
the new/modified comment object.
Upvotes: 1
Reputation: 34206
Instead of thinking about collapsing (v) think about setting the state to collapsed (adj). When the user clicks expand / hide, set a boolean. In your render function, check the boolean.
Something like this:
React.createClass({
getInitialState: function () {
return { hidden: false }
},
render: function () {
return (<div class={ this.state.hidden && 'hidden' } onClick={ this.toggle }>
{ this.props.children }
</div>)
},
toggle: function (ev) {
this.setState({ hidden: !this.state.hidden })
},
})
And in the css:
.hidden div { display: none; }
Edit: How to append divs
Stop thinking in verbs. You don't want to append (v) divs, you want divs to either be present (adj) or absent (adj). You can use another boolean, or whatever conditional you'd like:
render: function () {
return (<div>{ this.state.weWantDivs && this.renderDivs() }</div>)
}
Edit: How to put child view in parent view
Put the child elements in the parent element.
render: function () {
return <Parent><Child></Child></Parent>
}
And in the parent element render special children
property.
var Parent = React.createClass({
render: function () {
return <div>{ this.props.children }</div>
}
})
Upvotes: 3