meteor / react-packages

Meteor packages for a great React developer experience
http://guide.meteor.com/react.html
Other
574 stars 159 forks source link

useTracker not updating // parallel executions? #325

Closed thomasf1 closed 3 years ago

thomasf1 commented 3 years ago

I´m getting strange behaviour when trying to display Meteor.user() data like this:

const googleEmail = useTracker(() => {if (Meteor.user() && Meteor.user().services.google) {return Meteor.user()?.services.google?.email} else {return "loading..."}})

It sometimes displays the email and sometimes not.

Putting some console.logs in and a count each time it executes gives renders the count 3, not 4 as it should.

Debug js:

var debugData = useTracker(() => {runcount = runcount + 1; console.log('useTracker ran', Meteor.user(), runcount, Meteor.user()?.services.google?.email); return runcount})

Console output:

useTracker ran undefined 1 undefined
useTracker ran undefined 2 undefined
useTracker ran {_id: "29839283", profile: {…}, services: {…}} 3 undefined
useTracker ran {_id: "29839283", profile: {…}, services: {…}} 4 some@email.com

HTML rendered: 3 as runcount and no email

Any idea on how I could dig deeper?

CaptainN commented 3 years ago

I'm not sure what you are trying to do here, but there is a startup period for Meteor.user(). If Meteor.user() returns undefined (instead of an object or `null) it means it's still initializing. You'll need to work around that.

CaptainN commented 3 years ago

Also checkout: Meteor.loggingIn()

thomasf1 commented 3 years ago

Yes, I´m aware that I need to work around Meteor.user() returning undefined.

I´m trying to display Meteor.user()?.services.google?.email. Unfortunately that fails sometimes. Apparently the Meteor.user() triggers useTracker 4 times. Unfortunately somehow it just returns the information from the 3rd run somehow. I´m having a hard time understanding that behaviour.

filipenevola commented 3 years ago

@thomasf1 I don't think you should publish all your services to the client.

I usually copy the email to the first level of my user document in the Accounts.onCreateUser callback.

Maybe you are not publishing the services (which is good) and then your code is failing.

Your issue looks more a question than an issue.

The best place to ask questions is in the Forums or in our Community Slack.

Please send this question there and I'm sure you are going to get some help.

thomasf1 commented 3 years ago

Publishing some of the services if default behaviour and not really the issue here. Copying the email to the first level could be a workaround for a bug, but the useTracker really should not behave like it does in this instance.

It´s not a question. It´s a simple piece of code running/updating 4 times, but only the result of the 3rd run rendering.

It´s also simple to replicate: Set up a meteor, add react and google-accounts (or use any existing with services) and put in this code:

var runcount = 0
var debugData = useTracker(() => {runcount = runcount + 1; console.log('useTracker ran', runcount, Meteor.user()?.services.google?.email); return runcount})

Then, use it as such in react:

<div>Google: debugData {debugData}</div>

Refresh the page.

console output

useTracker ran 1 undefined
useTracker ran 2 undefined
useTracker ran 3 undefined
useTracker ran 4 some@email.com

Rendered:

Google: debugData 3

It might be some timing issue / race condition, but certainly not the expected behaviour of useTracker