Al momento so almeno tre modi per passare i nuovi dati a un componente:
- componente ri-renderizzare. Non preoccuparti dell'efficienza di questo metodo perché React sembra gestirlo molto bene. Ci sono bei articoli su questo: Change And Its Detection In JavaScript Frameworks e Updating with React.render
- Usa PubSub per consentire al componente di essere informato sulla modifica dei dati (alcuni esempi utili che puoi trovare nel post How to communicate between React components).
- vincolante con un callback (vedere tre jsfiddles qui sotto)
Per la terza opzione mi sono ispirato la risposta di StevenH ed esteso un po '. Si prega di verificare la mia implementazione a j sfiddle.net/kb3gN/12002/.
var Data = { value: 1 };
var dataChange = function(callback){
if(callback){
callback(Data);
setInterval(function(){
Data.value++;
callback(Data);
}, 1000);
}
return Data;
};
var World = React.createClass({
render: function() {
return <strong>{this.props.data.value}</strong>;
}
});
var Hello = React.createClass({
getInitialState: function() {
return {
data: this.props.dataChange()
};
},
componentDidMount: function() {
this.props.dataChange(this.updateHandler)
},
updateHandler: function(data) {
this.setState({
data: data
});
},
render: function() {
return (
<div>
Value: <World data={this.state.data} />
</div>
);
}
});
React.renderComponent(<Hello dataChange={dataChange} />, document.body);
Inoltre esiste una versione estesa a jsfiddle.net/kb3gN/12007.
function ListenersService(){
var listeners = {};
this.addListener = function(callback){
var id;
if(typeof callback === 'function'){
id = Math.random().toString(36).slice(2);
listeners[id] = callback;
}
return id;
}
this.removeListener = function(id){
if(listeners[id]){
delete listeners[id];
return true;
}
return false;
}
this.notifyListeners = function(data){
for (var id in listeners) {
if(listeners.hasOwnProperty(id)){
listeners[id](data);
}
}
}
}
function DataService(ListenersService){
var Data = { value: 1 };
var self = this;
var listenersService = new ListenersService();
this.addListener = listenersService.addListener;
this.removeListener = listenersService.removeListener;
this.getData = function(){
return Data;
}
setInterval(function(){
Data.value++;
listenersService.notifyListeners(Data);
}, 1000);
}
var dataSevice = new DataService(ListenersService);
var World = React.createClass({
render: function() {
return <strong>{this.props.data.value}</strong>;
}
});
var Hello = React.createClass({
getInitialState: function() {
return {
data: this.props.dataService.getData()
};
},
componentDidMount: function() {
this.props.dataService.addListener(this.updateHandler)
},
updateHandler: function(data) {
this.setState({
data: data
});
},
render: function() {
return (
<div>
Value: <World data={this.state.data} />
</div>
);
}
});
React.renderComponent(<Hello dataService={dataSevice} />, document.body);
Questa implementazione non è completamente seguendo l'idea di componenti isolati (perché componente Ciao dipende dalla API DataService), ma può essere estratta ulteriormente ed è compito dello sviluppatore di app che convenzioni specifiche app suoi componenti seguirà. Per esempio vedi il mix del primo e del secondo esempio su jsfiddle.net/kb3gN/12015 (oggetto HelloDataStatic e callbackHataDataDynamic)
Nota: il servizio Listeners utilizzato nell'esempio segue il pattern Observer e il pattern stesso ha più svantaggi che pro in molti scenari. Oltre a ciò, quello che volevo mostrare con questi esempi è il modo di legare i dati con un callback
<div id="static"></div>
<div id="dynamic"></div>
<script>
function ListenersService(){
var listeners = {};
this.addListener = function(callback){
var id;
if(typeof callback === 'function'){
id = Math.random().toString(36).slice(2);
listeners[id] = callback;
}
return id;
}
this.removeListener = function(id){
if(listeners[id]){
delete listeners[id];
return true;
}
return false;
}
this.notifyListeners = function(data){
for (var id in listeners) {
if(listeners.hasOwnProperty(id)){
listeners[id](data);
}
}
}
}
function DataService(ListenersService){
var Data = { value: 1 };
var self = this;
var listenersService = new ListenersService();
this.addListener = listenersService.addListener;
this.removeListener = listenersService.removeListener;
this.getData = function(){
return Data;
}
setInterval(function(){
Data.value++;
listenersService.notifyListeners(Data);
}, 100);
}
var dataSevice = new DataService(ListenersService);
var halloDataDynamic = function(callback){
var data = dataSevice.getData();
if(callback){
dataSevice.addListener(function(data){
callback(data);
});
}
return data;
};
var halloDataStatic = dataSevice.getData();
var World = React.createClass({
render: function() {
return <strong>{this.props.data.value}</strong>;
}
});
var Hello = React.createClass({
getInitialState: function() {
var data;
if(typeof this.props.halloData === 'function'){
data = this.props.halloData(this.updateHandler)
}
else data = this.props.halloData;
return {
data: data
};
},
updateHandler: function(data) {
this.setState({
data: data
});
},
render: function() {
return (
<div>
Value {this.props.name}: <World data={this.state.data} />
</div>
);
}
});
</script>
React.renderComponent(<Hello halloData={halloDataStatic} name="static"/>, document.getElementById('static'));
React.renderComponent(<Hello halloData={halloDataDynamic} name="dynamic"/>, document.getElementById('dynamic'));
Il livello del modello usa eventi? se è così puoi usarli per attivare un rendering. – krs
Ho aggiunto una domanda simile riguardante l'utilizzo dei modelli Backbone con React e come aggiornare le viste quando il modello aggiorna http://stackoverflow.com/questions/20371566/handling-backbone-model-collection-changes-in-react -js –
Hai trovato una soluzione? – copndz