I usually have this page structure:
return this.props.loaded ? <ActualPageComponent /> : <Loading />
So how do i properly check if my data is loaded and pass it to {loaded} props?
All i can think of are this options:
Check actuall values of data ie Boolean(Comments.find().fetch())
{loaded: Meteor.subscribe('comments').ready()}
ComponentDidMount() { this.state.loaded = true }
I really like the first option but it does not work. Comments.find().fetch() always returns an array ([] at the page load and [object, object] few moments after) so it is impossible to check data readinnes because many times i have zero data to fetch. For example if post has no comments to it.
none
May 19, 2016, 10:36am
2
Do you use redux? (-:
With redux I’m using react-redux-loading-bar , it’s very simple.
Here’s a full page implementation I’m using:
// my Container (parts of it)
export default createContainer((params) => {
const { campaignId } = params;
const sub = subsManager.subscribe('campaign.one', campaignId);
const loading = !sub.ready();
const campaign = Campaigns.findOne(campaignId);
...
return { loading, campaign, ...}
// my Page (parts of it)
export default class CampaignBucketsPage extends React.Component {
render() {
const {
loading,
error,
campaign,
...
} = this.props;
if (loading) return <LoadingPage />;
if (!campaign) return <ErrorBanner error="No Campaign" />;
if (error) {
return (
<div>
<CampaignTop currentTab="summary" campaign={ campaign } />
<ErrorBanner body={error}/>
</div>
);
}
return (
<div>
<CampaignTop currentTab="buckets" campaign={ campaign } />
// my LoadingPage component
import React from 'react';
import Card from '../../../ui/components/elements/Card';
import _ from 'lodash';
export class LoadingCounter extends React.Component {
constructor(props) {
super(props);
this.state = { elapsed: 0, start: (props.start || new Date()) };
}
componentDidMount() {
// componentDidMount is called by react when the component
// has been rendered on the page. We can set the interval here:
const tick = () => {
// This function is called every 50 ms. It updates the
// elapsed counter. Calling setState causes the component to be re-rendered
if (!this.state.start) return;
this.setState({ elapsed: new Date() - this.state.start });
return;
};
this.timer = setInterval(tick, 100);
}
componentWillUnmount() {
// This method is called immediately before the component is removed
// from the page and destroyed. We can clear the interval here:
clearInterval(this.timer);
}
getDuration() {
// const seconds = moment().diff(this.state.start, 'seconds');
const elapsed = Math.round(this.state.elapsed / 100);
const seconds = (elapsed / 10).toFixed(1);
if (seconds > 60) {
// TODO auto-notify server w/ AJAX call?
const min = (seconds / 60).toFixed(1);
return <span className="text-danger">
<i className="fa fa-warning" />
{min} min
</span>;
}
if (seconds > 20) {
return <span className="text-warning">
<i className="fa fa-warning" />
{seconds} sec
</span>;
}
if (seconds > 10) {
return <span className="text-warning">{seconds} sec</span>;
}
if (seconds > 5) {
return <span className="text-info">{seconds} sec</span>;
}
return <small className="text-info">{seconds} sec</small>;
}
render() {
return this.getDuration();
}
}
export default class LoadingPage extends React.Component {
render() {
return (
<figure className="figure">
<img
src="/img/animated-bull-drawing.gif"
className="figure-img img-fluid img-rounded"
alt="Loading..." />
<figcaption className="figure-caption text-xs-right">
<p>Loading... <LoadingCounter {...this.props} /></p>
</figcaption>
</figure>
);
}
}
LoadingCounter.propTypes = {
start: React.PropTypes.instanceOf(Date),
};
1 Like
Thank you for sharing.
Creating an component is a great idea. Also i never heard of subsManager. Going to try it out.