I using React to implemented Include ponent. It load content from url. This test works but also produces an unexpected infinite loop with render... why?
<script type="text/jsx">
/** @jsx React.DOM */
var Include = React.createClass({
getInitialState: function() {
return {content: 'loading...'};
},
render: function() {
var url = this.props.src;
$.ajax({
url: url,
success: function(data) {
this.setState({content: data});
}.bind(this)
});
return <div>{this.state.content + new Date().getTime()}</div>;
}
});
var Hello = React.createClass({
render: function() {
return <Include src="hello.txt" />;
}
});
React.renderComponent(
<Hello />,
document.getElementById('hello')
);
</script>
I using React to implemented Include ponent. It load content from url. This test works but also produces an unexpected infinite loop with render... why?
<script type="text/jsx">
/** @jsx React.DOM */
var Include = React.createClass({
getInitialState: function() {
return {content: 'loading...'};
},
render: function() {
var url = this.props.src;
$.ajax({
url: url,
success: function(data) {
this.setState({content: data});
}.bind(this)
});
return <div>{this.state.content + new Date().getTime()}</div>;
}
});
var Hello = React.createClass({
render: function() {
return <Include src="hello.txt" />;
}
});
React.renderComponent(
<Hello />,
document.getElementById('hello')
);
</script>
Share
Improve this question
edited Jul 20, 2014 at 2:44
Brigand
86.3k20 gold badges167 silver badges173 bronze badges
asked Jul 19, 2014 at 16:30
Antonio KobashikawaAntonio Kobashikawa
911 silver badge8 bronze badges
2 Answers
Reset to default 4This is a more reliable Include ponent. The differences,
- render should be pure (can't do ajax there)
- getInitialState should be pure
- if the prop is dynamic, e.g.
<Include url={this.state.x} />
, it should update
var Include = React.createClass({
getInitialState: function() {
return {content: 'loading...'};
},
ponentDidMount: function(){
this.updateAJAX(this.props.url);
},
ponentWillReceiveProps: function(nextProps){
// see if it actually changed
if (nextProps.url !== this.props.url) {
// show loading again
this.setState(this.getInitialState);
this.updateAJAX(nextProps.url);
}
},
updateAJAX: function(url){
$.ajax({
url: url,
success: function(data) {
this.setState({content: data});
}.bind(this)
});
},
render: function() {
return <div>{this.state.content}</div>;
}
});
var Hello = React.createClass({
render: function() {
return <Include src="hello.txt" />;
}
});
I realized render is executed a lot of times, so is not better place to my ajax invocation (-_-)'
This way works fine:
<script type="text/jsx">
/** @jsx React.DOM */
var Include = React.createClass({
getInitialState: function() {
var url = this.props.src;
$.ajax({
url: url,
success: function(data) {
this.setState({content: data});
}.bind(this)
});
return {content: 'loading...'};
},
render: function() {
return <div>{this.state.content + new Date().getTime()}</div>;
}
});
var Hello = React.createClass({
render: function() {
return <Include src="hello.txt" />;
}
});
React.renderComponent(
<Hello />,
document.getElementById('hello')
);
</script>
Thank you for reading!