2015-10-12 11 views
5

Coś dziwnego się dzieje, czytałem dokumentację React, a oni rozmawiają o cyklu życia i o tym, jak możesz zrobić coś niedobrego przed wyrenderowaniem komponentu. Próbuję, ale wszystko, czego próbuję, nie działa, zawsze komponent sprawia, że ​​renderowanie najpierw i po wywołaniu componenWillMount, ..didMount itd. I po wywołaniu tych funkcji, renderowanie dzieje się ponownie.Reactjs: Jak pobrać dane do załadowania przed zamontowaniem komponentu?

Najpierw muszę załadować dane, aby wypełnić stan, ponieważ nie chcę, aby stan początkowy był null, chcę go z danymi od początkowego renderowania.

Używam Flux i Alt, tutaj jest akcja

@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}); 
     }) 
    } 
} 

wtedy sklep

@createStore(flux) 
class GetDealersStore { 

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

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

} 

i składnik

@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> 
    ); 
    } 

} 

jak widać w części składowej mam ten

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

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

który mówi mi, że dealerData is undefined lub can not read property of null.

Wszystko, czego potrzebuję, to znać technikę, w której mogę pobrać dane przed wystąpieniem początkowego renderowania. Tak więc mogę wypełnić state i rozpocząć pracę z tymi danymi.

+0

Powiązane pytanie: http://stackoverflow.com/q/30329418/1233251 –

+0

@ E_net4 jest mój problem : 'Wywołuje się raz, zarówno na kliencie, jak i serwerze, bezpośrednio przed wystąpieniem początkowego renderowania. Jeśli wywołasz setState w tej metodzie, render() zobaczy zaktualizowany stan i zostanie wykonany tylko raz, pomimo zmiany stanu. ", Który wprawił mnie w zakłopotanie. – NietzscheProgrammer

+0

@ E_net4 w moim kodzie dodałem już instrukcję warunkową i wszystko jak w tym pytaniu i nie działa. Zobacz mój kod, spróbuj mi pomóc, proszę. – NietzscheProgrammer

Odpowiedz

3

React gwarantuje, że przypisania stanu w componentWillMount będą miały miejsce przed pierwszym renderowaniem. Jak dobrze napisano w komentarzach:

Wywołuje się jeden raz, zarówno na kliencie, jak i na serwerze, bezpośrednio przed wystąpieniem wstępnego renderowania. Jeśli wywołasz setState w tej metodzie, render() zobaczy zaktualizowany stan i zostanie wykonany tylko raz pomimo zmiany stanu.

Jednak akcje asynchroniczne, o które się prosili, nie zaktualizują natychmiast Twojego sklepu. Wywołanie GetDealersActions.getDealers(); spowoduje, że sklep zostanie zaktualizowany o nową treść, ale odpowiedź dotrze dopiero później w kolejce zdarzeń. Oznacza to, że this.props.dealersData nie zmienia się podczas działania i setState spróbuje odczytać właściwość "dealersData" niezdefiniowanej właściwości. Bez względu na to, żądana zawartość nie może być widoczna przy pierwszym renderowaniu.

Moja rada jest taka sama jak w przypadku similar question. Uniemożliwianie komponentowi renderowania tej zawartości, dopóki nie stanie się dostępna, tak jak Ty, jest odpowiednią rzeczą do zrobienia w programie. Możesz też wyrenderować program ładujący, gdy nie pojawi się "dealersData".


Dla rozwiązywania konkretnego problemu, usuń że setState z componentWillMount. Wszystko powinno działać dobrze, jeśli twój element macierzysty odpowiednio nasłuchuje zmian i propaguje je do rekwizytów dzieci.

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

, ale nadal dzieje się pierwsze renderowanie, a następnie wywoływane jest 'componentWillMount()'. Następnie program renderuje ponownie. – NietzscheProgrammer

+0

Na mocy umowy Reacta jest to niemożliwe. Albo wytyczyłeś inny obiekt React, albo w najgorszym przypadku mamy dziwny błąd. –

+0

Czekam na te dane z bazy danych, będą z tego powodu? – NietzscheProgrammer

1

Najlepszą odpowiedzią używać do odbierania danych z serwera i wyświetla je

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

Nie działa dla mnie .. –

+0

Ostrzeżenie: setState (...): Może aktualizować tylko zamontowany lub montowany komponent. Zwykle oznacza to, że wywołałeś setState() na odmontowanym komponencie. To nie jest operacja. Sprawdź kod komponentu ProfileController. –

Powiązane problemy