Reputation: 8589
I am waiting the props to come up from a store named GetDealersStore
, and the way I am fetching that data is with an action where I am doing this:
componentWillMount () { GetDealersActions.getDealers(); }
I already test the app and componentWillMount()
is running before the initial render where I have this
let dealerInfo;
if (this.state.dealerData) {
dealerInfo = this.state.dealerData.dealersData.map((dealer) => {
return (<div>CONTENT</div>);
})
} else {
dealerInfo = <p>Loading . . .</p>
}
but for the first second you can see <p>Loading . . .</p>
in the screen which is the else
in the conditional above, and then the rest of the render comes up with return (<div>CONTENT</div>);
which is the if
in the conditional. So, I guess, this means that the render method has been trigger twice because it keeps waiting for the data coming from the database.
The data from the database is not available at the time of the 1st render, so, how can I fetch that data before the 1st initial render occurs?
Upvotes: 9
Views: 18349
Reputation: 162
My answer is similar to Mathletics', just in more detail.
In this example I've included initialising state of dealerData to null; this is the check that's made to determine whether the data has been returned from the store by the container.
It's verbose, but declarative, and does what you want, in the order that you want, and it will work each time.
const DealerStore = MyDataPersistenceLibrary.createStore({
getInitialState() {
return {
dealerData: null
};
},
getDealers() {
// some action that sets the dealerData to an array
}
});
const DealerInfoContainer = React.createClass({
componentWillMount() {
DealerStoreActions.getDealers();
},
_renderDealerInfo() {
return (
<DealerInfo {...this.state} />
);
},
_renderLoader() {
return (
<p>Loading...</p>
);
},
render() {
const { dealerData } = this.state;
return (
dealerData
? this._renderDealerInfo()
: this._renderLoader()
);
}
});
const DealerInfo = React.createClass({
getDefaultProps() {
return {
dealerData: []
};
},
_renderDealers() {
const { dealerData } = this.props;
return dealerData.map(({ name }, index) => <div key={index}>{name}</div>);
},
_renderNoneFound() {
return (
<p>No results to show!</p>
);
},
render() {
const { dealerData } = this.props;
return (
dealerData.length
? this._renderDealers()
: this._renderNoneFound()
);
}
});
Upvotes: 8
Reputation: 36592
You can't do this with a single component. You should follow the Container Component pattern to separate data from rendering.
let DealersContainer = React.createClass({
getInitialState() {
return {dealersData: []};
},
componentWillMount() {
GetDealersActions.getDealers();
},
render() {
let {dealersData} = this.state;
return (<div>
{dealersData.map((dealer) => {
let props = dealer;
return (<Dealer ...props />); // pass in dealerData as PROPS here
})}
</div>);
}
});
Then update your Dealer
component to receive props and render the actual content.
Upvotes: 13