Can't see the collection's data when using withTracker (for react)


#1

hi, I’m trying to create a meteor app with react on the client. Everything goes well, besides working with “withTracker”, as I can’t seem to see the mongo collection’s data inside the component. (error: Cannot read property ‘name’ of undefined)

I created a very basic example, but I’m still doing something wrong. would be great if someone could help me understand what I missed.

thanks!

collection: (please note that I DO see the collection in the minimongo meteor extension tab inside the dev tools, so the problem isn’t importing it)

import { Mongo } from 'meteor/mongo';

const Items = new Mongo.Collection('items');

export default Items;

server:

import { Meteor } from 'meteor/meteor';
import Items from '../imports/api/items';

Meteor.startup(() => {
  Items.insert({name: 'A'});
});

component:
please note: if I change the data returned inside he withTracker from a Items.find()… to a simple string it works so the problem must be there.
also, im still using the auto publish and insecure packs, so I don’t think I must subscribe to the data, right?

import React, { Component } from 'react';
import Items from '../api/items';
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';

class App extends Component {
    state = {
        name: 'a'
    }

    componentDidMount() {
        this.setState({
            name: this.props.element.name
        })
    } 

    render() {

        return (
            <div>
                <header>{this.state.name}</header>
            </div>
        )
    }
}


export default AppContainer = withTracker(({}) => {
    return {
        element: Items.findOne({}) 
    };
  })(App);

thanks!


#2

You need to publish data on the server side and subscribe on the client side.


#3

I don’t know how you do this woth react but with Blaze I use something like Meteor.subscribe(‘items’) to subscribe to the collection in the client.


#4

Yes, you need to subscribe to the publication to see data in your collection.

Check http://www.meteor-tuts.com/chapters/1/intro.html for a good tutorial.

And check the meteor guide with react.


#5

So can you see the element comes with props to your container?
I guess your Items.findOne({}) triggers after componentDidMount, so the solution is to use props to get all the reactive data, like:

render() {
  const {element = {}} = this.props;
  return (<div>{element.name}</div>)
}

#7

i also think that this may be the reason.

not sure i understand const {element = {}} - what does it mean?

thanks!


#8

I don’t think it has to do with the subscribing as I use auto-publish and also if I return a console.log, in the beginning I get an undefined and later I CAN see the object from the collection.

so now i assume its because the component did mount renders before it gets the data so I get an error.

any recommendations about how to fix ( like async await or an if conditions for the data)?

thanks :slight_smile:


#9

try to call setState in constructor(props) and in componentWillReceiveProps(nextProps) function.
Before set state, you must check the props before, because it takes time to finish subscribe data.


#10

Take a look a this : http://www.meteor-tuts.com/chapters/2/react.html

So ok, you use the insecure package… Don’t forget to remove it after your training. And you will need to change your code with publication and subscription.

In your react component, you need to assume that element is undefined at first.
So don’t use state, use props.

In the render function you can check if element is undefined or not and show information in consequence.

And const {element = {} } = this.props it’s the same that : const element = this.props.element ? this.props.element : {}

If you want to have state, so use componentWillreceiveProps, or other methods from the life cycle of react :slight_smile:


#11

it’s ES6 syntax, Destructing Assignment. it equals to const element = this.props.element


#12

hi, thanks!

This was the issue.

thanks for the explanation :slight_smile:


#13

right, i forgot about that.

thank you :slight_smile: