@sashko i’ve noticed that a lot of times getMeteorData would re-run more times than it needs to which can cause a lot of UI lag… one example was every key press triggered multiple re-renders which made it a bit laggy.
Is there a set of do’s/dont’s as far as how to structure the function? One thing I noticed is that scoping down the things tracker is watching can help (either with fields or wrapping with another component).
To be honest I haven’t used it lately (mostly Redux) so perhaps these were resolved already.
@sylar can you paste in your getMteorData method in so we can troubleshoot?
still, people just ignore the edge case when user is not logged in or user collection is not yet on client.
So render something other when it is not defined, do not try to render that user in render() till it is defined.
Render some placeholder element instead.
In general, in Meteor, we’ve gotta be careful info we want to be reactive. If we use Meteor.user() in a computation, then that will be reactive when absolutely any info inside the user object changes, which can be lots if the user object has lots of changing info.
I read somewhere (can’t find it at the moment) that if you want to react to a specific property of a document, you can do just that with the fields option, which will cause reactive updates less often and perform better:
Meteor.users.findOne(id, {fields: {"profile.foo": 1}}) // react only to changes on profile.foo
Additionally, we can throttle reactivity and limit it to, say, at most one update per 2-second time window:
let profileFoo = new ReactiveVar('') // initial value of empty string
let setProfileFoo = _.throttle(value => profileFoo.set(value), 2000)
// ^ fire this logic at most once in any
// given 2-second period of time.
// See http://underscorejs.org/#throttle
Tracker.autorun(computation => {
let foo = Meteor.users.findOne(id, {fields: {"profile.foo": 1}})
setProfileFoo(foo)
})
class Foo extends React.Component {
render() {
// this render method will only fire at most once per 2 seconds.
}
getMeteorData() {
// will only change at most once in any 2-second time window, and only on the profile.foo property!
let foo = profileFoo.get()
return {foo}
}
}
We use TrackerReact instead of MeteorGetData and, in case anybody tried, would be interested to know if there is any difference. We actually use it in production and render about 1000 items in virtual lists :?
Sorry for the absence. UK bed time called but Im awake now. I’ll go through the replies and see what works best. Thanks for all replies!
Edit:
I think I have not sent the message correctly. Why your solution will not work? I’m not rendering anything so I can not render something else while I wait on their data to be loaded in client. Maybe what I want can be done another way? I’m still learning Redux but for now I’ll try with pure React and Meteor.
I want to bind a user profile field. So far what I did only works in Chrome but getMeteorData() is slow in other browsers. The scenario is, when a user is on their profile page, all fields will be blank. Now they will fill in the blanks then hit update. Now…those fields have the value of what was entered and they can update at will.
even with fast-render, do not expect user collection to be available all the time.
So test if this.data.user is available inside render(), if not return placeholder dom element.
If it is available you can return your form.
Nothing is needed in componentDidMount(), that getMeteorData will take care of re-renders during all changes of user record.
when you have your subscription in some higher component, than use that component to render form only when it is already ready and pass there props whatever you want and do not render that form component before user data are ready.
that way you can initiate your form state based on passed properties from parent component.