Reputation: 437
I have been working with ReactJS for a while. I would say I like it.
But some components life-cycles are still fogy for me. For example, I am trying to create a component who loads data only once from server.
On componentDidMount
I am going not only load data but use some third-party libraries (for example jQuery components).
Below I have a very simple component with button and list. When user click the button it loads some comments into the list by AJAX request and show this list to user. When we click button again we hide this list.
So here I have questions:
ReactElement
and it executes
componentDidMount
.Please, do not suggest use display: none;
)
Feel free to execute this example on jsfiddle.
var jsonData = {
"comments" : [
{id: 1, comment: "Comment 1"},
{id: 2, comment: "Comment 2"},
{id: 3, comment: "Comment 3"},
{id: 4, comment: "Comment 4"}
]
};
var CommentsBox = React.createClass({
getInitialState: function () {
return {
comments: [],
loading: true
}
},
componentDidMount: function () {
var dxInstanceElement = this.refs.dxInstanceElement;
$(dxInstanceElement).dxDataGrid(this.getDataGridOptions());
},
render: function () {
var commentsNode = this.state.comments.map(function(comment){
return (
<p key={comment.id}>{comment.comment}</p>
);
});
return (
<div>
{this.state.loading && <img src="http://www.ajaxload.info/images/exemples/21.gif" />}
<div>Total count of comments: {this.state.comments.length}</div>
<div ref="dxInstanceElement" />
</div>
);
},
getDataGridOptions: function () {
return {
dataSource: this.getDataGridDataSource(),
selection: {
mode: "multiple"
},
columns: [{
dataField: "comment",
caption: "comment"
}]
};
},
getDataGridDataSource: function () {
var self = this,
urlAPI = "http://jsonplaceholder.typicode.com/comments";
var myStore = new DevExpress.data.CustomStore({
load: function (/*loadOptions*/) {
var d = $.Deferred();
$.ajax({
type: 'POST',
dataType: 'json',
url: '/echo/json/',
data : {
json: JSON.stringify( jsonData ),
delay: 3
},
success: function(data) {
d.resolve(data.comments, {totalCount: data.comments.length});
self.setState({
loading: false
});
}
});
return d.promise();
}
});
return new DevExpress.data.DataSource({
store: myStore
});
}
});
var DemoRouterExample = React.createClass({
getInitialState: function () {
return {
submited: false
};
},
onClick: function() {
var submited = this.state.submited;
this.setState({
submited: !submited
});
},
render: function () {
var btnLabel = this.state.submited ? "hide list" : "load list";
return (
<div>
<button type="button" onClick={this.onClick}>{btnLabel}</button>
{this.state.submited && <CommentsBox />}
</div>
);
}
});
ReactDOM.render(
<DemoRouterExample />,
document.getElementById('container')
);
Upvotes: 2
Views: 343
Reputation: 7045
I'm not exactly sure what's the problem here but I would place the Ajax call and the corresponding state at the same level. Here maybe put your Ajax call in the parent componentdidMount
then pass it as a prop to the child.
Upvotes: 0
Reputation: 757
I believe the reason is that you use {this.state.submited && <CommentsBox />}
,when submit
was set to false, the CommentsBox
is unmounted. The next time you set submit
true, CommentsBox
is mounted again.
I suggest you using <CountriesBox show={this.state.submited} />
instead. And in CommentsBox
:
return (
<div className={this.props.show ? '' : 'hide'}>
<div>Total count of comments: {this.state.comments.length}</div>
{commentsNode}
</div>
);
the hide
class just set to display:none;
NOTE that that ajax will execute immediately you render the DemoRouterExample
. Because CommentsBox
is always been render.
Upvotes: 2