Pass a prop to a Meteor.method and get back the result

Seems simple, but something is off.

I have a Table component which takes a data source. In order to get the date, I call a function which calls a method on the server.

I can see the result coming back as expected, but the dataSource does not seem to get it. My guess is this.getMembers() returns null before the callback.

In essence, I want to pass a prop to a Meteor.method and get back the result.

<Table rowKey="_id" pagination={false} loading={false} dataSource={this.getMembers()} columns={columns} />

getMembers: () ->
    Meteor.call("getMembers", this.props.activeList.members, (error, result) ->
      if error
        error
      else
        console.log("getMembers: " + result)
        result)

I tried a new approach of placing everything in the withTracker.

export default MemberListContainer = withTracker( () =>
  handle = Meteor.subscribe('allMembers')
  loading: !handle.ready()
  listMembers: Members.find({_id: {$all: ["u48osfAPQXGF3KMss"] }}).fetch()
  currentUser: Meteor.user()
  activeList: Lists.findOne({ _id: Session.get("activeList") })

The above code works, but I need to replace the hard coded string "u48osfAPQXGF3KMss" with the actual array of Ids in this.props.activeList.members, but that’s not available. Maybe I should assign this.props.activeList.members to a Session variable somehow?

You can grab the value you need earlier in the container component (While handling the case that it’s not ready yet):

export default MemberListContainer = withTracker( (props) => {
    const handle = Meteor.subscribe('allMembers');
    const loading = !handle.ready()
    const activeList = Lists.findOne({ _id: Session.get("activeList") })
    
    let listMembers;
    if (activeList) {
        listMembers = Members.find({_id: {$all: [activeList.members] }}).fetch();
    }
    
    return  {
        loading,
        activeList,
        listMembers,
        currentUser: Meteor.user(),
    }
});

Also, you can pass props into withTracker wrapped components, which can save you from being tightly coupled to global session state

Ah, looks nice. This would save me a lot of data duplication on the server.

I tried to implement and everything works, but this.props.listMembers returns empty. I think activeList isn’t ready when I hit the IF statement - therefore it skips the listMembers = Members.find....

Might be a coffeescript thing. Code below. Any insight?

export default MemberListContainer = withTracker( (props) =>
  handle = Meteor.subscribe('allMembers')
  loading = !handle.ready()
  activeList = Lists.findOne({ _id: Session.get("activeList") })

  if activeList
    listMembers = Members.find({_id: {$in: [activeList.members] }}).fetch()

  {
    loading
    activeList
    listMembers
    currentUser: Meteor.user()
  }

Oh I missed this but you should subscribe to lists as well, otherwise loading will only tell you when Members are in minimongo, but if you don’t have the List listMemebers will never be ready:

export default MemberListContainer = withTracker( (props) ->
  handles = [
    Meteor.subscribe('allLists')
    Meteor.subscribe('allMembers')
  ]
  loading = handles.some(handle => !handle.ready())
  activeList = Lists.findOne({ _id: Session.get("activeList") })

  if activeList
    listMembers = Members.find({_id: {$all: [activeList.members] }}).fetch()

  ready = !loading && activeList && listMembers.length > 0
  {
    loading
    ready
    activeList
    listMembers
    currentUser: Meteor.user()
  }

I also added ready as a sanity checking thing. After this is working, you can probably ditch it.

I like the change. Added the new handlers, but listMembers is still coming back . I console.logged activeList.members in the IF branch and it is returned accurately as an array of Ids, I just think the Members.find call is not coming back in time.

Honestly, not sure. Maybe I need a different pattern to join.

(Didn’t change the issue, but I had $all instead of $in - fixed in my code)

These functions are synchronous, if the client has the data it will be returned.


Okay, then it sounds like a query problem?

If you put a breakpoint on Members.find and run Members.find().fetch() in the console, does any data appear? (The function should run a few times, when the handles come back as ready and when find starts returning data, so check at the stage when activeList.members exists)

Otherwise it might be a variable scope issue (not sure how it works in coffeescript)