2016-02-11 18 views
21

Sto ottenendo il seguente avvisoReagire setState può aggiornare solo un componente montato o montaggio

"Attenzione: setState (...): Può aggiornare solo montato o un componente di montaggio Questo di solito significa che hai chiamato setState.() su un componente non montato. Questo è un non operativo. Controllare il codice per il componente ContactPage. "

Quando inizialmente vado alla pagina di contatto, la prima volta va bene. Quindi, se esco dalla pagina e torno indietro, l'avviso viene lanciato.

Pagina contatto componente:

import React, { Component, PropTypes } from 'react'; 
import AppStore from '../../stores/AppStore'; 
import AppActions from '../../actions/AppActions'; 
import DataContent from './DataContent'; 

const title = 'Contact Us'; 


class ContactPage extends Component { 

    constructor(props) { 
     super(props); 
     this.state = AppStore.getState(); 
     AppActions.getData(); 
    } 

    static contextTypes = { 
    onSetTitle: PropTypes.func.isRequired, 
    }; 

    componentWillMount() { 
    this.context.onSetTitle(title); 
    AppStore.listen(this.onChange.bind(this)); 
} 

componentWillUnmount() { 
    AppStore.unlisten(this.onChange.bind(this)); 
} 

onChange(state) { 
    this.setState(state); 
} 

renderData() { 
    return this.state.data.map((data) => { 
     return (
      <DataContent key={data.id} data={data} /> 
     ) 
    }) 
} 

    render() { 
    return (
     <div className={s.root}> 
     <div className={s.container}> 
      <h1>{title}</h1> 
      <div> 
       { this.renderData() } 
      </div> 
     </div> 
     </div> 
    ); 
} 

} 

export default ContactPage; 

Quando ho messo in debugger, il carico di pagina di contatto colpisce componentWillMount(). Quando esco dalla pagina dei contatti, colpisce componentWillUnmount(). Quando torno alla pagina, colpisce ancora componentWillMount() e poi genera l'errore quando colpisce la funzione onChange (stato).

risposta

36

Il problema è che il listener dell'istanza del componente precedente è ancora registrato. E poiché l'istanza precedente non è più montata, ottieni questo errore.

.bind restituisce sempre una nuova funzione . Quindi se lo fai

AppStore.unlisten(this.onChange.bind(this)); 

quindi stai cercando di rimuovere un ascoltatore che non esiste (che fallisce ovviamente). Lo fa non rimuovere l'ascoltatore si raccomandata con AppStore.listen(this.onChange.bind(this))


Per risolvere questo problema, è necessario associare il gestore volta nel costruttore:

this.onChange = this.onChange.bind(this); 

e quindi utilizzare AppStore.listen(this.onChange) e AppStore.unlisten(this.onChange).

+0

ha funzionato! Grazie :) – erichardson30

+3

". Bind restituisce sempre una nuova funzione" .... mind blown !!! – CambridgeMike

+0

Grazie per questo. Ho lottato con esso per un paio d'ore. – Avdept

6

Prima del cambiamento, il componente di controllo stato è montato.

render() { 
    return (
    <div ref="root" className={s.root}> 
     // ---- 
    </div> 
    )}; 

onChange(state) { 
    if(this.refs.root) { 
    this.setState(state); 
    } 
} 

Penso che questo possa esserti d'aiuto.

0

Nel proprio caso aggiungere un riferimento al div root e controllare il valore di riferimento prima di chiamare setState.

tuo onChange metodo dovrebbe apparire in questo modo:

onChange(state) { 
    this.refs.yourRef ? this.setState(state) : null;  
} 
-1

ero alle prese con questo problema e per un bel po '.

Ciò che ha risolto per me era fare come proposto da @Felix Kling, ma assicurarmi anche che la mia funzione di callback fosse dichiarata all'interno della classe del componente, altrimenti non si è in grado di usare il prefisso this, che apparentemente era il trucco per me.

Ecco un esempio di ciò che intendo:

legale, ma non funziona

function onChange() { 
    this.setState({ MyState: newState }) 
} 

class MyComponent extends React.Component { 
    constructor(props) { 
    super(props); 
    onChange = onChange.bind(this); 
    } 

    componentDidMount() { 
    window.addEventListener('resize', onChange); 
    } 

    componentWillUnmount() { 
    window.removeEventListener('resize', onChange); 
    } 

    render() { ... } 
} 

Opere

class MyComponent extends React.Component { 
    constructor(props) { 
    super(props); 
    this.onChange = this.onChange.bind(this); 
    } 

    onChange() { 
    this.setState({ MyState: newState }) 
    } 

    componentDidMount() { 
    window.addEventListener('resize', this.onChange); 
    } 

    componentWillUnmount() { 
    window.removeEventListener('resize', this.onChange); 
    } 

    render() { ... } 
} 

Speranza che aiuta chiunque e Affrontare questo problema. :)

Problemi correlati