9

Given a MyQuestionStore store:

class MyQuestionStore {
  @observable asked = 'today';
  @observable answered = false;
  @observable question = {
    upvotes: 0,
    body: null,
    asker: null,
    askerPoints: null,
    askerBadges: null
  }
  // some more initial state observables...
  // some actions below...
}

const myQuestionStore = new MyQuestionStore();
export default myQuestionStore;

What would be the correct way to reset all store observables back to their initial states data ('today'/false/0/null/etc..)?

NOTE: Something like MyQuestionStore.reset() for example I think would be a good MobX way, but I don't think it exists. I would have to write an action called reset and manually reset each observable back to its initial state. I don't think that would be the right way, since if I add more observables, I would have to manually add them to the reset action every time.

raphinesse
  • 13,873
  • 4
  • 33
  • 44
Wonka
  • 5,762
  • 17
  • 59
  • 108
  • MobX does not track the previous values, so a manual reset you are talking about is not a bad idea. – Tholle Sep 04 '16 at 08:00
  • I see.. I think even if MobX doesn't track them that's okay. I was thinking maybe a method can "snapshot" the initial state of the observables, and pull it back out on hitting the `reset()` I am just trying to figure out a way without having to manually maintain observables reset one by one (in case I forget to add an observable in the reset). – Wonka Sep 04 '16 at 14:49
  • Can't you just create a new store based on the same class? – Adam Gerthel May 27 '18 at 18:25

5 Answers5

8

EDIT: this is an old answer that doesn’t work in newer versions of mobx.

If you use the reset() to initialize the object, you could avoid duplication of code. Here is what I mean:

import { extendObservable } from "mobx";

class MyQuestionStore {
  constructor() {
    this.reset();
  }

  @action reset() {
    extendObservable(this, {
      asked: 'today',
      answered: false,
      question: {
        upvotes: 0,
        body: null,
        asker: null,
        askerPoints: null,
        askerBadges: null
      }
    });
  }
}
Mouad Debbar
  • 2,658
  • 1
  • 18
  • 18
  • 1
    Works very well, thank you! One minor edit is semicolons should be commas (SO won't allow me to just change them on an answer unless I change 6 characters, which I don't need to do) :) – Wonka Sep 12 '16 at 17:34
  • `extendObservable()` doesn't reset existing observables, so it sounds like running `reset()` outside of the constructor wouldn't actually have the desired effect. So, in short, this doesn't work. – Dygerati May 01 '18 at 07:17
  • @Dygerati I'm quite confident this snippet was working in older versions of mobx. I'm not up-to-date with the latest changes in mobx, would you mind adding a snippet that would work for the recent versions of mobx? – Mouad Debbar May 02 '18 at 06:57
  • @MouadDebbar Understood, that makes sense. I'm actually not aware of a working method to do this so far, but I'll report back if I come up with anything. – Dygerati May 11 '18 at 21:43
4

I ended up having to repeat the default observables in the reset function, so it looks like this:

class MyQuestionStore {
  @observable asked = 'today';
  @observable answered = false;
  @observable question = {
    upvotes: 0,
    body: null,
    asker: null,
    askerPoints: null,
    askerBadges: null
  }

  @action reset = () => {
    this.asked = 'today';
    this.answered = false;
    this.question = {
      upvotes: 0,
      body: null,
      asker: null,
      askerPoints: null,
      askerBadges: null
    }
  }
}

const myQuestionStore = new MyQuestionStore();
export default myQuestionStore;

I still feel there is a better way than to repeat it and keep it DRY. I will keep the question open for now, hoping there is a better DRY answer.

Wonka
  • 5,762
  • 17
  • 59
  • 108
  • I heard that combination of mobx's `toJS` and lodash `deepMerge` worked well for others – mweststrate Sep 13 '16 at 17:15
  • hmmm.. didn't know that as I've never used `deepMerge` from lodash. Thanks for sharing and for the awesome mobx! – Wonka Sep 13 '16 at 23:35
4

If you don't need to reset deeply, the createViewModel utility from mobx-utils might come in handy: https://github.com/mobxjs/mobx-utils/#createviewmodel

mweststrate
  • 4,547
  • 1
  • 14
  • 22
  • Hmmm... Yeah I think I am trying to reset deeply regardless of the number of times the observable was changed, sort of back to the base line default. – Wonka Sep 07 '16 at 17:10
1

To reset store you can do something like this:

const initialValue = {
  name: 'John Doe',
  age: 19,
}

@action reset() {
  Object.keys(initialState).forEach(key => this[key] = initialState[key]);
}

And you can set initial store values:

class myStore {
  constructor() {
    extendObservable(this, initialState);
  }
}
0

Why not going with the following approach

class MyQuestionStore {
   @observable asked;
   @observable answered;
   @observable question;

   constructor() {
      super()
      this.init()
   }

   @action reset() {
      this.init()
   }

   @action init() {
     this.asked = 'today';
     this.answered = false;
     this.question = {
         upvotes: 0,
         body: null,
         asker: null,
         askerPoints: null,
         askerBadges: null
      }
   }

  // some more initial state observables...
  // some actions below...
}

const myQuestionStore = new MyQuestionStore();
export default myQuestionStore;
Itamar
  • 1,371
  • 1
  • 8
  • 20