[Solved] Can't get collection data from withTracker to show up

When trying to render, I get ‘item is not defined’. I think it’s trying to render before the data comes back. (note, I’m not using pub/sub yet as in early dev)

import React, { Component } from 'react'
import Lists from '../api/lists'
import { withTracker } from 'meteor/react-meteor-data'
import { List } from 'antd'

class MyLists extends Component
  render: () =>
    (<List
      size="small"
      header={<div><strong>My Lists</strong></div>}
      bordered
      dataSource={this.props.myLists}
      renderItem={item => (<List.Item>{item.name}</List.Item>)}
    />)

export default MyListsContainer = withTracker( () =>
  myLists: Lists.find({admins: {$in: [Meteor.userId()]} }).fetch()
)(MyLists)

If I use this, then data shows up:

class MyLists extends Component
  render: () =>
    for list in this.props.myLists
      <p key={list._id} >{list.name}</p>

I guess I am just note getting the pattern for using withTracker props in a react component. Thanks for any insight.

I’m guessing by this you mean you still have the autopublish package installed?
Because if so, you are using pub/sub.

If not, how are you loading data into minimongo / Lists?

Yes, still have autopublish.

When using autopublish, the same rules as normal Meteor pub/sub apply.
All autopublish does is automatically set up publications and subscriptions for every collection so you can focus on prototyping instead of boilerplate or the nitty gritty of data segmentation.

Normally in React, loading state is passed down by checking the subscription handle. But I don’t think you can access that with autopublish on.

The alternatives are to

  • check for a falsy value in your component (similar to a loading check)

    class MyLists extends Component {
        render = () =>
            !this.props.myLists ? 
                <p>Loading...</p> :
                (<List
                    size="small"
                    header={<div><strong>My Lists</strong></div>}
                    bordered
                    dataSource={this.props.myLists}
                    renderItem={item => (<List.Item>{item.name}</List.Item>)}
                />)
    }
    
  • Or write some some simple publications and subscriptions

    // server/main.js
    Meteor.publish('allLists', function () { return Lists.find() });
    
    // container code:
    export default MyListsContainer = withTracker( () => {
        const handle = Meteor.subscribe('allLists');
        return {
            loading: handle.ready(),
            myLists: Lists.find({admins: {$in: [Meteor.userId()]} }).fetch()
        }
    })(MyLists)
    
    // Then check in component. Will re-render when ready
        render = () =>
            !this.props.loading ? 
                <p>Loading...</p> :
                (<List etc...
    

Thanks for the guidance. Trying to implement, but the data still isn’t coming back at all.

on server

Meteor.publish('allLists', () ->
  Lists.find({ }) )

on client

class MyLists extends Component

  render: () =>
    exists = !this.props.loading && !!this.props.myLists
    console.log("myLists is " + this.props.myLists)
    console.log("loading is " + this.props.loading)
    console.log("exists is " + exists)

    if exists
      <p>Yep</p>
    else
      <p>Nope</p>

export default MyListsContainer = withTracker( () =>
  myLists: Lists.find({admins: {$in: [Meteor.userId()]} }).fetch()
  handle = Meteor.subscribe('allLists')
  loading: !handle.ready()
  currentUser: Meteor.user()
)(MyLists)

In my UI I see ‘Nope’.

IN my console I see:

myLists is undefined
loading is true
exists is false
...
myLists is undefined
loading is false
exists is false

So everything is working, but the myLists isn’t coming back for some reason.

Solved by placing my Lists.find()… below the handle in the withTracker function. See below:

export default MyListsContainer = withTracker( () =>
  handle = Meteor.subscribe('allLists')
  loading: !handle.ready()
  currentUser: Meteor.user()
  myLists: Lists.find({admins: {$in: [Meteor.userId()]} }).fetch()
)(MyLists)

Well that’s frustrating that order matters!

Glad you got it working in the end :slight_smile:

Indeed! Thank you for your guidance on subscriptions. It was time to switch it on and it makes the code cleaner. Appreciate it.