2014-07-19 14 views
5

I utilizzando React per implementare il componente Includi. Carica contenuto dall'URL. Questo test funziona ma produce anche un ciclo infinito inaspettato con render ... perché?Reactjs loop infinito inatteso con il rendering

<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> 

risposta

1

ho capito il rendering viene eseguito un sacco di volte, quindi non è un posto migliore per la mia invocazione ajax (-_-)'

In questo modo funziona bene:

<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> 

Grazie per leggere!

+2

Sono contento di vedere che ha lavorato fuori il problema! Un piccolo suggerimento che consiglio è di spostare la chiamata ajax nel metodo componentWillMount. Il risultato è lo stesso, ma utilizzando il metodo componentWillMount si ottiene una migliore separazione delle preoccupazioni. Ho attaccato un violino così puoi capire cosa intendo. P.S - React è impressionante Ecco il [jsfiddle] (http://jsfiddle.net/NXCyC/50/) – user3508122

+1

@ user3508122 Credo componentDidMount è corretto per questo. È usato nel [tutorial ufficiale] (http://facebook.github.io/react/docs/tutorial.html). L'unica ragione per cui posso pensare è che componentWillMount viene chiamato quando si usa 'renderComponentToString' (cioè rendering del server). – FakeRainBrigand

+0

@FakeRainBrigand - Buon posto! Hai ragione, mio ​​errore. – user3508122

4

Questo è un componente Includi più affidabile. Le differenze,

  • rendering dovrebbe essere puro (non possono fare ajax ci)
  • getInitialState deve essere puro
  • se l'elica è dinamico, ad esempio <Include url={this.state.x} />, si dovrebbe aggiornare
var Include = React.createClass({ 
    getInitialState: function() { 
    return {content: 'loading...'}; 
    }, 
    componentDidMount: function(){ 
    this.updateAJAX(this.props.url); 
    }, 
    componentWillReceiveProps: 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" />; 
    } 
});