From 41580fdaf5ca47db282c8321aa334b691178867c Mon Sep 17 00:00:00 2001 From: Kevin Newman Date: Wed, 27 Jan 2021 20:10:07 -0500 Subject: [PATCH] Fix lost reactivity when using deps --- .../react-meteor-data/useTracker.tests.js | 35 ------------------- packages/react-meteor-data/useTracker.ts | 13 ++++--- 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/packages/react-meteor-data/useTracker.tests.js b/packages/react-meteor-data/useTracker.tests.js index a1e37a21..b473e923 100644 --- a/packages/react-meteor-data/useTracker.tests.js +++ b/packages/react-meteor-data/useTracker.tests.js @@ -220,41 +220,6 @@ if (Meteor.isClient) { completed(); }); - Tinytest.addAsync('useTracker - basic track', async function (test, completed) { - var container = document.createElement("DIV"); - - var x = new ReactiveVar('aaa'); - - var Foo = () => { - const data = useTracker(() => { - return { - x: x.get() - }; - }, []); - return {data.x}; - }; - - ReactDOM.render(, container); - test.equal(getInnerHtml(container), 'aaa'); - - x.set('bbb'); - await waitFor(() => { - Tracker.flush({_throwFirstError: true}); - }, { container, timeout: 250 }); - - test.equal(getInnerHtml(container), 'bbb'); - - test.equal(x._numListeners(), 1); - - await waitFor(() => { - ReactDOM.unmountComponentAtNode(container); - }, { container, timeout: 250 }); - - test.equal(x._numListeners(), 0); - - completed(); - }); - // Make sure that calling ReactDOM.render() from an autorun doesn't // associate that autorun with the mixin's autorun. When autoruns are // nested, invalidating the outer one stops the inner one, unless diff --git a/packages/react-meteor-data/useTracker.ts b/packages/react-meteor-data/useTracker.ts index 9dfabe36..01063193 100644 --- a/packages/react-meteor-data/useTracker.ts +++ b/packages/react-meteor-data/useTracker.ts @@ -106,12 +106,15 @@ const useTrackerNoDeps = (reactiveFn: IReactiveFn) => { const useTrackerWithDeps = (reactiveFn: IReactiveFn, deps: DependencyList): T => { let [data, setData] = useState(); + const { current: refs } = useRef({ reactiveFn }); + refs.reactiveFn = reactiveFn; + useMemo(() => { // To jive with the lifecycle interplay between Tracker/Subscribe, run the // 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(); + if (c.firstRun) data = refs.reactiveFn(); }) ); // To avoid creating side effects in render, stop the computation immediately @@ -122,9 +125,11 @@ const useTrackerWithDeps = (reactiveFn: IReactiveFn, deps: Dependenc }, deps); useEffect(() => { - const computation = Tracker.autorun((c) => { - setData(reactiveFn(c)); - }); + const computation = Tracker.nonreactive( + () => Tracker.autorun((c) => { + setData(refs.reactiveFn(c)); + }) + ); return () => { computation.stop(); }