Tracker.flush() for template-scoped Trackers (this.autorun)

Hello and happy new year, everyone.

I’ve got a UI event (user presses a button) triggering a query parameter change, and a tracker watching that query parameter (via FlowRouter.getQueryParam(), which is reactive).

I’m calling Tracker.flush() in my event handler but it doesn’t seem to fix the delay. Is there a template-specific way to call flush()? I don’t see one. It feels wrong to call the global Tracker.flush() when my autorun was setup in the context of a template instance anyway.

Template.example.onCreated(function() {
  this.autorun(() => {
    const show = FlowRouter.getQueryParam('show') // Reactive
    // ... show the UI ...
  })
})

Template.example.events({
  'click button': function(e, template) {
    FlowRouter.setQueryParams({ show: 1 })
    Tracker.flush() // <--- doesn't fix the delay
  },
})

I inspected ‘this’ and don’t see any kind of tracker property, etc.

Any thoughts/suggestions? Thanks!

So Tracker.flush() I’d the only way to call flush, this.autorun pretty much just calls Tracker.autorun anyway, with some pieces to bond the view.

Ultimately, changing a dependency just means that on the next iteration of the event loop, all functions that depend on that will change.

Flush should trigger this early, but there’s no guarantee that flow router does the set immediately. I’d suggest handling this yourself, without reactivity if the delay is intolerable, though generally I’ve never even needed a flush and there is no noticable delay.

1 Like

So I’m looking at this again and the issue is that calling FlowRouter.setQueryParams() causes the entire route to re-render. This makes sense for a lot of use cases I’m sure, but in my case, I simply want to set the parameter so my reactive FlowRouter.getqueryParams() code will execute - not ro re-render.

Anyone happen to know a good pattern for this kind of behaviour?

I tried throwing my setQueryParams() call into a FlowRouter.withReplaceState() callback but that didn’t seem to help.

Thanks.

OK so I’ve got a workaround. Posting in case it’s useful to anyone else.

It would be nice to be able to use FlowRouter for this, but for now I just call the following func, which uses window.pushState to avoid FlowRouter re-rendering the entire page:

	setQueryParamsWithoutFlowRouterRerender(params) {
		const url = new URL(window.location)

		Object.keys(params).forEach(k => {
			const v = params[k]
			if (v) {
				url.searchParams.set(k, params[k])
			} else {
				url.searchParams.delete(k) // Remove a param from the URL if its value is null, like FlowRouter.setQueryParams() does
			}
		})

		window.history.pushState({}, '', url)
	}