How to persist Reactive Dicts across routes & set optional defaults?


#1

Firstly, I am trying to persist reactive dicts across route changes. As suggested on the atmosphere readme, I named my dict in a Template.onCreated() so it stays across hot code pushes. No problems with that.

this.state = new ReactiveDict('discoverPageState');

But when I change routes (I’m using FlowRouter) and come back to that page my console throws this error.

Error: Duplicate ReactiveDict name: discoverPageState

Secondly, is it possible to set optional defaults for a dict? When this page is created I either want to use the existing state or set defaults. I’ve tried this with no luck.

this.state.setDefault({ requested: this.state.get('requested') || PAGE_SIZE, discoverCategory: this.state.get('discoverCategory') || 'All', discoverTime: this.state.get('discoverTime') || 'this week', discoverSort: this.state.get('discoverSort') || 'popularity', discoverRadius: this.state.get('discoverRadius') || 20, discoverLocation: this.state.get('discoverLocation') || null, locationSearchResults: this.state.get('locationSearchResults') || null, findingLocation: this.state.get('findingLocation') || false });

I would appreciate any advice / help. If theres a better way to set defaults me know! Thanks.


#2

Looks like the variable is being persisted when you change your route. So once you navigate to your template again it will try to createa new once hence the error…you can just catch it with and if statement.


#3

As you suggested I wrapped the reactive dict in an if statement, but I’m still getting the same error. Am I doing this wrong? My new code is below. I really wish reactive-dict had better documentation.

if (!this.state) {
    this.state = new ReactiveDict('discoverPageState');

    this.state.setDefault({
      requested: PAGE_SIZE,
      discoverCategory: 'All',
      discoverTime: 'this week',
      discoverSort: 'popularity',
      discoverRadius: 20,
      discoverLocation: null,
      locationSearchResults: null,
      findingLocation: false
    });
  }

#4

the problem here is that this.state is bound to the template but you are declaring a global

This means you switch routes and the variable gets deleted but the global ReactiveDict('discoverPageState') does not.
The next time you navigate to the page this.state will be undefined (as it was deleted when you left the page) so it goes into the if statement but then it tries to create another ReactiveDict with the same name.

So two things:

  1. Depending on how you are using you Dict you should probably assign a global variable to it, since it is global anyways. You could init the global on startup and assign a value to it in the template. If you do it that way you will not have to use the statement in point two. You can just check if your global has certain values.
  2. If you want to check if your reactive dict already exist you have to call
    if (ReactiveDict._dictsToMigrate['discoverPageState'] === undefined)

I did not find documentation on this but you can look at the package itself and the two files (migration / reactive-dict)

You can also think of just using Sessions here which is basically the same but API might be nicer.


#5

Awesome shibbn. Thanks for the help, you sniped what was going on. I was using Sessions previously but wanted to switch to a dict based on the guide’s recommendation. I’m using the first method you suggested for this, importing the variable on startup, and it works great.