2015-10-12 8 views
5

Sta succedendo qualcosa di strano, ho letto i documenti di React e loro parlano del ciclo di vita e di come si può fare qualcosa prima che il componente venga reso. Ci sto provando, ma tutto quello che provo è fallito, sempre il componente effettua il rendering prima e dopo chiama componentenWillMount, ..didMount, ecc. E dopo il richiamo di quelle funzioni, il rendering avviene di nuovo.Reactjs: come recuperare i dati da caricare prima che il componente sia montato?

Ho bisogno di caricare i dati prima per riempire lo stato perché non voglio che lo stato iniziale sia null, lo voglio con i dati dal rendering iniziale.

Sto usando Flux e Alt, qui è l'azione

@createActions(flux) 
class GetDealersActions { 

    constructor() { 
    this.generateActions('dealerDataSuccess', 'dealerDataFail'); 
    } 

    getDealers (data) { 
    const that = this; 
    that.dispatch(); 
    axios.get(`${API_ENDPOINT}/get-dealers/get-dealers`) 
     .then(function success (response) { 
     console.log('success GetDealersActions'); 
     that.actions.dealerDataSuccess({...response.data}); 
     }) 
    } 
} 

poi il negozio

@createStore(flux) 
class GetDealersStore { 

    constructor() { 
    this.state = { 
     dealerData : null, 
    }; 
    } 

    @bind(GetDealersActions.dealerDataSuccess) 
    dealerDataSuccess (data) { 
    this.setState({ 
     dealerData : data, 
    }); 
    } 

} 

e la componente

@connectToStores 
export default class Dealers extends Component { 

    static propTypes = { 
    title : React.PropTypes.func, 
    } 

    static contextTypes = { 
    router : React.PropTypes.func, 
    } 

    constructor (props) { 
    super(props); 
    this.state = { 
     modal : false, 
     dealerData : this.props.dealerData, 
    } 
    } 

    componentWillMount() { 
    GetDealersActions.getDealers(); 
    this.setState({ 
     dealerData : this.props.dealerData.dealersData, 
    }) 
    } 

    static getStores() { 
    return [ GetDealersStore ]; 
    } 

    static getPropsFromStores() { 
    return { 
     ...GetDealersStore.getState(), 
    } 
    } 

    render() { 

    return (<div> 
      <div style={Styles.mainCont}> 
      {!!this.props.dealerData ? 
       this.props.dealerData.dealersData.map((dealer) => { 
       return (<div>HERE I AM RENDERING WHAT I NEED</div>); 
       }) : <p>Loading . . .</p> 
      } 
      </div> 
     </div> 
    ); 
    } 

} 

come si può vedere nella componente ho questo

constructor (props) { 
    super(props); 
    this.state = { 
     modal : false, 
     dealerData : this.props.dealerData, 
    } 
    } 

    componentWillMount() { 
    GetDealersActions.getDealers(); 
    this.setState({ 
     dealerData : this.props.dealerData.dealersData, 
    }) 
    } 

che mi sta dicendo che dealerData is undefined o can not read property of null.

Tutto ciò di cui ho bisogno è conoscere una tecnica in cui posso recuperare i dati prima che si verifichi il rendering iniziale. Così posso compilare il state e iniziare a lavorare con quei dati.

+0

Una questione collegata: http://stackoverflow.com/q/30329418/1233251 –

+0

@ E_net4 c'è il mio problema : 'Invocato una volta, sia sul client che sul server, immediatamente prima del rendering iniziale. Se chiami setState con questo metodo, render() vedrà lo stato aggiornato e verrà eseguito solo una volta, nonostante il cambiamento di stato. "Questo mi ha confuso. – NietzscheProgrammer

+0

@ E_net4 nel mio codice Ho già aggiunto un'istruzione condizionale e tutto come in quella domanda e non funziona. Guarda il mio codice, cerca di aiutarmi, per favore. – NietzscheProgrammer

risposta

3

React garantisce che le assegnazioni di stato in componentWillMount si svolgeranno prima del primo rendering. Come ben specificato nei commenti:

Invocato una volta, sia sul client che sul server, immediatamente prima del rendering iniziale. Se si chiama setState all'interno di questo metodo, render() vedrà lo stato aggiornato e verrà eseguito solo una volta, nonostante il cambiamento di stato.

Tuttavia, le azioni asincrone richieste non aggiorneranno immediatamente il tuo negozio. Se chiami il numero GetDealersActions.getDealers();, lo store viene aggiornato con nuovi contenuti, ma la risposta arriverà solo più tardi nella coda degli eventi. Ciò significa che this.props.dealersData non cambia durante la funzione e setState tenterà di leggere la proprietà "dealersData" di una proprietà non definita. Indipendentemente da ciò, il contenuto richiesto non può essere visibile al primo rendering.

Il mio consiglio è uguale a quello di similar question. Impedire al componente di rendere quel contenuto finché non diventa disponibile, come hai fatto tu, è una cosa appropriata da fare in un programma. In alternativa, esegui il rendering di un loader mentre i tuoi "dealersData" non sono arrivati.


Per risolvere il tuo problema particolare, rimuovere che setState da componentWillMount. Tutto dovrebbe funzionare bene se il componente genitore sta ascoltando correttamente le modifiche e propagandole ai materiali di scena per bambini.

componentWillMount() { 
    GetDealersActions.getDealers(); 
} 
+0

ma si verifica ancora il primo rendering, quindi viene chiamato 'componentWillMount()'. Successivamente, il programma esegue nuovamente il rendering. – NietzscheProgrammer

+0

Secondo il contratto di React, è impossibile. O hai tracciato un altro oggetto React da renderizzare, o nel peggiore dei casi abbiamo uno strano bug. –

+0

Sto aspettando questi dati dal Database, sarà per quello? – NietzscheProgrammer

1

La migliore risposta che uso per ricevere i dati dal server e visualizzarlo

constructor(props){ 
     super(props); 
     this.state = { 
      items2 : [{}], 
      isLoading: true 
     } 

    } 

componentWillMount(){ 
axios({ 
      method: 'get', 
      responseType: 'json', 
      url: '....', 

     }) 
      .then(response => { 
       self.setState({ 
        items2: response , 
        isLoading: false 
       }); 
       console.log("Asmaa Almadhoun *** : " + self.state.items2); 
      }) 
      .catch(error => { 
       console.log("Error *** : " + error); 
      }); 
    })} 

render() { 
    return(
     { this.state.isLoading && 
        <i className="fa fa-spinner fa-spin"></i> 

       } 
       { !this.state.isLoading && 
      //external component passing Server data to its classes 
        <TestDynamic items={this.state.items2}/> 
       } 
     ) } 
+0

Non funziona per me .. –

+0

Avvertenza: setState (...): Può aggiornare solo un componente montato o montato. Questo di solito significa che hai chiamato setState() su un componente non montato. Questo è un no-op. Si prega di verificare il codice per il componente ProfileController. –

Problemi correlati