-
Notifications
You must be signed in to change notification settings - Fork 160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useTracker problem - Can't set timers inside simulations #396
Comments
Ran into the same problem as well. Strangely it only happens to me on Firefox and works fine in Brave. Meteor 2.13 The code: import { Meteor } from 'meteor/meteor'
import { useEffect } from 'react'
import { useSubscribe } from 'meteor/react-meteor-data'
import { ProfilesCollection } from 'meteor/socialize:user-profile'
import type { Profile } from '../../users/definitions'
import { Tracker } from 'meteor/tracker'
import { ReactiveVar } from 'meteor/reactive-var'
const profileData = new ReactiveVar<Profile | null>(null)
export function useProfile(subscription?: string): {
isLoading: boolean
profile: Profile | null
} {
const isLoading = useSubscribe(subscription || 'profile')
useEffect(() => {
const computation = Tracker.autorun(() => {
if (!isLoading()) {
const profile = ProfilesCollection.findOne(Meteor.userId())
profileData.set(profile) // same issue if I use React.useState
}
})
return () => {
computation.stop()
}
}, [])
return { isLoading: isLoading(), profile: profileData.get() }
} The logs seems to point to |
Found the solution for the additional error triggered, unrelated to this. one. Also I have switched back to using instead of The suspense version:
Seems to resolve it in many places for me. |
I'm not sure what a "simulation" is in this context, but it's probably this line in useTracker. Basically, we are using a trick to avoid some side effects in some edge cases. That deserves a closer look in React 18+. Most of those edge cases were problems with earlier versions of React's concurrency model. It's probably all different now. |
@StorytellerCZ That example of using a computation in useEffect is basically a very simple implementation of a useTracker hook. It doesn't try to do any first-render magic that the main useTracker does, which has a lot of upside (simplicity especially) and only a few downsides, especially if your components are properly composed, and you don't do some giant single component iterator. Basically, whenever you build your component output off something derived from state in useEffect, you essentially opt out of concurrent rendering (at least that's how it used to work). That's not always terrible - in the case of loading data, it's often preferable, as you avoid a lot of edge case problems, and you can opt back in to concurrent rendering by just defining the components that actually do the rendering separately (instead of using a branching statement and a lot of JSX in a single loading component). (So treat the component that does the loading as a container.) What I've been finding working with react server components, suspense and some newer tech, is that the old HOC/container model is becoming the norm again, but it looks a lot different than the way it used to. It's built off hooks, not HOCs for the data loaders - HOC/container is defined in the project. It's pretty interesting to see this all come full circle. Nextjs's app router is looking a lot like Meteor these days. |
Also, this error: |
The error message is gone after some work on our Error Boundary. We will also slowly start the process of separating data loading and the rest. As mentioned above using the suspense version of Maybe it is time to make a new breaking version release that removes the tricks for older Reacts and is only focused on React 18 (especially given that it has been around long enough). |
@StorytellerCZ That was part of the idea behind useFind and useSubscribe, though maybe we didn't go far enough. MOST of the challenge with implementing a general purpose useTracker comes from supporting the various Blaze compatible lifecycle hacks inside of the subscribe method. Everything else is kind of easy to support. It's worth reiterating, the side-effect we create when supporting a Tracker instance is NOT ONLY data loading, it's creating and maintaining computations, which can draw data from many locations - usually synchronously. Data loading is handled by subscriptions, which happens behind a computation. That's what makes this all so challenging. Almost all of the newest tools introduced by React 18 and server components is about data loading, and direct subscriptions. They haven't really added much to help us support computations. (Apollo Client and URQL have similar challenges when using their advanced caching, but they also have constrained problem domains, since they are only dealing with data loading, and not general purpose computations.) |
If I were blue skying this, I'd probably look at coming up with fresh implementation of Meteor.subscribe and look at that entire data loading pipeline, and not try to keep computations as they currently exist around. |
Yuck, ran into this bug again when trying to upgrade to Meteor 3. Had to migrate one component away from suspense (as for some reason it got into a loop of fetching data until hitting rate limit), but when I added a new entry I got this error again on the new post which seem to happen when getting profile, which was behind a suspense. It is all very confusing. |
I think with Meteor 3 and React 19 just about to be released, it might be a good time to look on the underlying issues and removing old workarounds. |
Code that causes the issue on my side (all hooks are suspense versions): const profile = useTracker(
`profileCard-${userId}`,
() => {
if (!userId) return null
return ProfilesCollection.findOne({ _id: userId })
},
[userId],
) If I do this, I don't get the error: const profiles = useFind(ProfilesCollection, [{ _id: userId }, { limit: 1 }], [userId])
const profile = profiles[0] |
I'm using
useTracker
like this:Works fine if contact is set from the start - but whenever
contact
changes from being null to non-null, this error occurs:Also tried
useTracker
with subscription as dep (same error as above) and without deps - which causes this error:The text was updated successfully, but these errors were encountered: