2016-04-26 28 views
6

Ho un componente nella mia app React che esegue il rendering di un valore totale per l'utente. Quando questo valore aumenta, voglio suonare un rumore. Ho pensato che all'interno del componente che visualizza il totale sarebbe un buon posto per riprodurre quel rumore da.nextProps sempre identici a this.props in componentWillReceiveProps, anche quando gli oggetti di scena sono cambiati

così ho aggiunto un metodo componentWillReceiveProps al componente, e in essa, ho calcolare due totali: total è calcolata da this.props e nextTotal è calcolata da nextProps.

Con mia grande sorpresa, anche quando i valori cambiano, e il cambiamento totali, nextTotal e total sono sempre lo stesso. Quindi il condizionale che voglio sparare quando il totale sale non succede mai.

Ho scritto un semplice esempio a componente singolo. JSfiddle.

var Hello = React.createClass({ 
    componentWillReceiveProps: function(nextProps) { 
    var total = 0; 
    this.props.vals.forEach(val => total+= val); 

    var nextTotal = 0; 
    nextProps.vals.forEach(val => nextTotal+= val); 

     console.log(total, nextTotal) 

    if (nextTotal > total) { 
      //never runs 
      console.log('moving up'); 
     } 
    }, 
    render: function() { 
    var total = 0; 
    vals.forEach(val => total+= val) 
    return (
     <div>{total}</div> 
    ) 
    } 
}); 

var vals = [1, 21, 452, 123]; 

setInterval(renderReact, 1000) 

function renderReact() { 
    vals.push(10); 
    ReactDOM.render(
    <Hello 
     vals={vals} 
    />, 
    document.getElementById('container') 
); 
} 

Come si può vedere, ogni secondo aggiunge 10 al vals matrice, il che significa che il totale si muove da 1. Ma se si apre la console, si può vedere che total e nextTotal sono sempre gli stessi, e moving up non viene mai registrato.

Sto chiaramente fraintendendo qualcosa di, e se qualcuno potesse spiegare qual è il mio fraintendimento, e come dovrei ottenere quello che sto andando, sarebbe fantastico.

+0

perché non provare a registrare i due array? controlla di continuare a spingere dieci per entrambi ... https: //jsfiddle.net/ydaso4cs/2/ che sono la stessa cosa ... – JordanHendrix

+4

Stai passando l'array direttamente all'elemento. 'this.props.vals' e' nextProps.vals' fanno riferimento allo stesso oggetto. – PitaJ

+0

non solo stai facendo riferimento allo stesso array, il tuo componente non si sta aggiornando poiché stai chiamando il rendering una volta. Non vedo alcun codice che causa un aggiornamento. –

risposta

10

Come indicato nei commenti (di @PitaJ), il problema è che si passa in una matrice per la prima volta, quindi si modifica la matrice, anziché chiamare con una nuova proprietà. Hai raggiunto l'oggetto in cui il tuo componente ha un riferimento come sua proprietà esistente e ne ha modificato il contenuto.

Nel vostro violino, provate questo:

function renderReact() { 
    vals.push(10); 
    ReactDOM.render(
    <Hello 
     vals={vals.concat([])} 
    />, 
    document.getElementById('container') 
); 
} 

Passaggio di una copia della matrice come il vostro prop ogni volta, vedrete differiscono in modo appropriato.

Questa è in realtà una fonte di errore non banale nell'utilizzo di reagire e può verificarsi anche quando si utilizza Redux se i riduttori non sono stati scritti con attenzione. L'uso di strutture di dati immutabili è un modo per evitarlo.