Adrian Soleil Adrian Soleil - 3 months ago 30
React JSX Question

React/Meteor init function when data is fully rendered

I do have the following React Component, which subscribes to MongoDB loads the images from it and returns to the page.

export default class Portfolio extends TrackerReact(React.Component) {

constructor(props) {
super(props);
this.state = {
subscription: {
albumbs: Meteor.subscribe('albums')
}
}
}

componentWillUnmount() {
this.state.subscription.albums.stop();
}

albums() {
return Albums.find().fetch();
}

render() {

function init () {
$('.carousel').flickity({
// options
"lazyLoad": true
});
};



return (
<ReactCSSTransitionGroup component='div' className='carousel' transitionName='postLoad' transitionLeaveTimeout={2000} transitionEnterTimeout={2000}>
{this.albums().map( (album) => {
return <div className='carousel-cell' key={album._id}><AlbumCover albums={album} /></div>
})}
{init()}
</ReactCSSTransitionGroup>
);
}
}


The current init function makes successful init carousel classes, but it looks like the data is loaded faster then the carousel is inited and thought images are nested outside of carousel slider.

enter image description here

Answer

Your subscription is not yet ready and your carousel function is triggering before all data is subscribed to, that's why you are having the error.

You have to make sure you are fully subscribed to your collection. Try to create a reactive container, set up a few Session variables and subscribe properly (import container via import {createContainer} from 'meteor/react-meteor-data'):

export default createContainer(() => {
  const subscription = Meteor.subscribe('albums');
  subscription.ready() ? Session.set("subReady", true) : Session.set("subReady", false);

  return{
    album: Albums.find().fetch(),
  }
}, Portfolio);

then in your render() component:

render(){
  if(Session.get("subReady")){
  return (
     <ReactCSSTransitionGroup component='div' className='carousel'  transitionName='postLoad' transitionLeaveTimeout={2000} transitionEnterTimeout={2000}>
      {this.albums().map( (album) => {
        return <div className='carousel-cell' key={album._id}><AlbumCover  albums={album} /></div>
      })}
      {init()}
    </ReactCSSTransitionGroup>
   );
}
}

and not to forget, add the carousel code in your componentDidMount() method:

componentDidMount(){
  if(Session.get("subReady")){
    function init () {
   $('.carousel').flickity({
     // options
     "lazyLoad": true
   });
 };
  }
}

I didn't test this code on my computer, but hopefully it works out for you.

If you want to use your method of subscribing, then make sure that:

1) The subscription is ready.

2) Make sure your carousel code is in your componentDidMount() method and is wrapped in a reactive way to trigger when the data is actually ready/subscribed to.