-
Notifications
You must be signed in to change notification settings - Fork 162
Fix issue with useTracker and Subscriptions when using deps #306
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
Conversation
- Fixes an edge case bug where Subscriptions could get lost or thrash - Cleans up typescript defs - Add resubscript tests for with deps variant, and reorg test groupings - Simplifies implentation - Removes undocumented computation handler
Hey @CaptainN this looks great. Did you intend to bump the version in this PR too? |
@dburles I typically leave that for the release engineer. The minor version number should at least be bumped. A bunch of internals changed. It's more than a bug fix release. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor version bump makes sense to me. I'll leave it to @filipenevola to handle the release.
Getting a console error when running a page with
Not a problem with react-meteor-data 2.1.0 |
Using useTracker single subscription. Running fine on [email protected] with react-meteor-data 2.1.4. Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering. |
Hi @Jerry360-bit could you open an issue with a reproduction? Read more here |
Hi @filipenevola, Thanks for your reply. Meteor and React newbie here trying to get back into coding after being gone for about 15 years.... I was using useTracker(fn ,[]). This worked with react-meteor-data 2.1.4 but not in 2.2.1. Understand react-meteor-data is undergoing changes. I will just try to keep up and learn more about it..... |
I am having a problem with that fix after updating from meteor 2. I always getting React: “Maximum update depth exceeded” and I am stuck and my system is down for 3 days now. even I do not use any useEffect() in my code! after debugging an researching for 3 very log days I found this 'fix' and I believe it is not a fix it has broken my code so please help here is my useTracker() code which was working fine before upgrading
|
@Jerry360-bit thank you for your comment. It helped me a lot and my system is working again |
@msgfxeg What specifically fixed the issue? What wasn't working, vs. what changed to make it work? |
@CaptainN Thank you for your concern and for asking. What was not working after upgrading from v2.1.4 to the latest version is useTracker(fn, [arrayOfDependencies]) even after weaving out the dependencies array still not working! what I have changed to make it work again is downgrading to v2.1.4 of react-meteor-data by editing the meteor packages file i.e. .meteor/packages from react-meteor-data to be react-meteor-data@=2.1.4 after that my system is up and running again. |
I downgraded to 2.1.4 too, in my case the new version seemed to triggered an immediate rerender where the previous version did not, and this interrupted a framer-motion transition. I haven't done any more specific debugging yet, as downgrading fixed the issue for me. |
I think I have an idea as to what's going on here. I think the I'll patch this later tonight. |
@rijk That FramerMotion problem is not likely to be solved by the fix I described above - but you should also know, that under some situations, the old hook will do that too... (You may be able to workaround that by using For that type use case, you may need the experimental For the issue of the error we have been discussing, if you remove the deps array altogether, does that fix the problem? (if you do that, it should use the |
Can you guys confirm that when removing the deps array (not just using an empty array) the problem persists? |
Not sure if you were asking me as well, but I cannot remove the array as there are actual deps in it. |
For me the problem clears when not using any deps array. Using an empty array the problem persists. |
@rijk You actually should be able to. Deps is optional in |
I am running Two examples of what I am experiencing:
In both cases the problem can be generalized to the following: On a fresh query, with a waterfall of hooks (
Another problem I have with the pagination example is that, if multiple consultations of the same pages are linked to the same patient, sometimes, only a subset of the patients are loaded successfully, the others hang forever. All these problem go away if I remove dependency arrays in Are my problems related to what is being discussed here? |
@aureooms Oh hey, you are here. PR #314 should fix these problems. I'd appreciate it if you could give that a test. In case you haven't done that before, you can do test by downloading/checking out the bugfix branch, and copying the |
@CaptainN I confirm using |
Could a hook waterfall be used as regression test for this fix? |
Like 0ce6d70, fixes #166, but without removing the deps arrays. See: - meteor/react-packages#306 - meteor/react-packages#314
@aureooms I'm not sure what you mean, but maybe. I think there were up to 2 problems:
Another thing we should write tests for is cases where deps are used incorrectly (like someone uses an object ref which will change on every render - easy to write a test for that one). This probably wouldn't have worked in 2.2.1 because of issue #2 above, but we should still not allow the hook to fail in these cases. It might even be possible to detect this in some way during development, and kick up a helpful warning, similar to that |
@CaptainN What utterance are you referring to? |
// reactive function in a computation, then stop it, to force flush cycle. | ||
const comp = Tracker.nonreactive( | ||
() => Tracker.autorun((c: Tracker.Computation) => { | ||
if (c.firstRun) data = reactiveFn(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we not using setData(reactiveFn())
here as it is done below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because that would cause an immediate rerender. The idea here is to temporarily override the value of data during the initial render (or immediately after deps change). Then when the component is mounted the next tracker instance set up in useEffect
will update the state data.
There is an assumption made here, which I'm not confident in, that the initial render will never be run more than once before useEffect is run. I'm thinking that might not be true if a user invokes an immediate rerender themselves (by triggering some hook in render). I can actually write a test for this.
I already have a mitigation in place for this possibility, but I don't want to push it until I've confirmed it's needed.
https://github.com/meteor/react-packages/blob/better-handle-data-with-refs/packages/react-meteor-data/useTracker.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found an issue #327
As a solution we can store it in useRef with flag initialized
, which turn to true after useEffect.
Something like:
function useTracker(){
...
const tempData = useRef({result:undefined, initialized:false});
...
if(comp.firstRun) {
tempData.current.result = refs.reactiveFn();
tempData.current.initialized = false;
}
...
useEffect(()=>{
...
const res = refs.reactiveFn(c);
setData(res);
tempData.current.result = undefined;
tempData.current.initialized = true;
...
return () => {
computation.stop();
tempData.current.result = undefined;
tempData.current.initialized = false;
};
});
...
return !tempData.current.initialized ? (tempData.current.result : data) as T;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of the things I changed in #321 was to keep the value of the first render in a ref - can you try that branch and see if it solves your issue?
I was referring to this:
|
@CaptainN Something like the following const useStuff = (stuff) => {
const things = useThings(stuff);
const foo = useFoo(things);
const bar = useBar(foo);
// ...
}; |
The runtime performance characteristics of the hook changed enough to warrant a minor version bump.