Withtracker with subscribe and publish always returns undefined

Hello,
I need to check if user has requested free demo in react. So in my server/main.js i have included
Meteor.publish(‘freeDemos’,function(){
return FreeDemo.find({
ownerId:this.userId
});
})

in Client/main.js
export default withTracker((props)=>{
Meteor.subscribe(‘freeDemos’);
const hasDemo = FreeDemoDB.findOne({
ownerId : Meteor.userId()
});
return { hasDemo : FreeDemoDB.findOne({
ownerId : Meteor.userId()
}) }
})(FreeDemo);

i have console.log in react constructor hasDemo. It runs only one time with undefined. My collection has one record.

I did tried in componentwillmount and its working there. but i dont want to put code there.

Can you please help?

Thank you!

At the start, hasDemo will be empty because the subscription is being initialized. After the initialization, the component is already mounted so placing it in the constructor means that props.hasDemo will be undefined.

Use getDerivedStateFromProps() instead or componentDidUpdate() depending on what you wanted to do. Check React’s documentation of getDerivedStateFromProps() for proper use.

A useful thing to do is to pass along a “loading” prop along with the hasDemo from the withTracker,

const loading = !Meteor.subscribe("freeDemos").ready();

You can then handle both the case of sub still loading, and sub ready in a predictable way

Thank you for the reply. Shouldn’t withTracker call again automatically once the data is ready? For me its not calling?

Thank you. Just tried it now and component is “Loading” as withTracker is not triggering again I think.

Could you post your whole files? You can make it look like code if you select it and press the Preformatted text above the text field too

var like = this;
import React, { Component } from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import { Tracker } from "meteor/tracker";

import { FreeDemo as FreeDemoDB } from '../../../imports/collections/user/freedemo';
class FreeDemo extends Component {
  constructor(props){
    super(props);
    this.state ={
      user : {},
      readOnly : false,
      error:"",
      buttonLabel : "Request Free Demo",
      title : 'Provide your contact details. We will Contact you Shortly'
    }
    console.log(this.props);
  }

  componentWillMount() {
    this.tracker = Tracker.autorun(()=>{
      this.setState({
        user:Meteor.user(),
      });
    });
  }
  reqFreeDemo(){
    if(this.state.readOnly){
      this.setState({
        error : "Demo already requested."
      })
      return;
    }
  if(!this.refs.name.value || !this.refs.email.value || !this.refs.mobile.value){
    this.setState({
      error : "All fields are Mandatory!"
    })
    return;
  }
  Meteor.call('demo.request',{
      name : this.refs.name.value,
      email : this.refs.email.value,
      mobile : this.refs.mobile.value
  },(error) => {
    if(error){
      this.setSate({
        error:error.reason
      })
    }else{
      Meteor.call('notification.new',{
        message :{
          title : 'You requested free demo',
          description: 'You have requested free demo. Our team will contact you shortly. Thank you for choosing us'
        },
        user : Meteor.userId(),
        link : ''
      },(error) => {
        console.log(error);
      })
    }
  })
  }
  render(){


    return (
      <div className="main-wrap">
        
          </div>
        );
  }
}

export default withTracker((props)=>{
  Meteor.subscribe('freeDemos');
  let hasDemo = FreeDemoDB.findOne({
                              ownerId : Meteor.userId()
                            });
  return {

    hasDemo : FreeDemoDB.findOne({
                              ownerId : Meteor.userId()
                            }) }
})(FreeDemo);

Server/main.js

import { Meteor } from 'meteor/meteor';

import './accounts/config.js';
import './accounts/account-creation.js';

// Collections
import { Event } from '../imports/collections/user/events';
import { Notification } from '../imports/collections/user/notification';
import { FreeDemo } from '../imports/collections/user/freedemo';

Meteor.startup(() => {


  // User notification publications
Meteor.publish('alerts',function(){
  return Notification.find({
    ownerId:this.userId
  });
});
Meteor.publish('shortAlerts',function(){
  return Notification.find({
    ownerId:this.userId
  },{limit:5});
});

Meteor.publish('hasDemo',function(){
  console.log( FreeDemo.find({
    ownerId:this.userId
  }));
  return FreeDemo.find({
    ownerId:this.userId
  });
})
})

;

Are you getting any errors in browser console or on the server? Does the console.log in the hasDemo publish run? (you are missing a .fetch() there to actually get anything

I20180830-19:38:09.785(5.5)? Exception from sub hasDemo id ghWJ3n32w4jtXLxQW Error: Publish function can only return a Cursor or an array of Cursors
I20180830-19:38:09.786(5.5)?     at Subscription._publishHandlerResult (packages/ddp-server/livedata_server.js:1129:18)
I20180830-19:38:09.786(5.5)?     at Subscription._runHandler (packages/ddp-server/livedata_server.js:1060:10)
I20180830-19:38:09.787(5.5)?     at Session._startSubscription (packages/ddp-server/livedata_server.js:859:9)
I20180830-19:38:09.787(5.5)?     at Session.sub (packages/ddp-server/livedata_server.js:625:12)
I20180830-19:38:09.788(5.5)?     at packages/ddp-server/livedata_server.js:559:43

Any Idea? I did search in google but they occur for different reason. What I am doing normal publish way?

don’t add fetch to the return query, just to the query inside console.log

but there is no `Meteor.publish(‘freeDemos’);

Thank you for the help :slight_smile: