mobxjs / mobx

Simple, scalable state management.

Home Page:http://mobx.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Migration from Mobx 4 > 6

Bidrman opened this issue · comments

Hey guys, I appreciate all the work you doing, but your migration guide aint the best one I have ever seen. Therefore I gotta ask you several questions, because I got stucked in my project upgrade.

Section Getting Started:

  • in step 3 and 6 you mention about the configure object. I assume all the settings are put togerther at one place, like so?
configure({
	enforceActions: "never",
	useProxies: "never",
});

if not, then it could be mentioned somewhere.

Section Upgrading clesses to use makeObservable:

  • well here it was mostly confusing, since I didnt write whoel project, I just inherited it and my first task is to upgrade mobxv4 to v6.
  • Since we have nearly 180 script, where we use decorators I decided for option 2.

"Leave all the decorators and call makeObservable(this) in the constructor. This will pick up the metadata generated by the decorators. This is the recommended way if you want to limit the impact of a MobX 6 migration."

  • where should I put the calling of makeObservable(this); ? Is it before calling a super() or after? I always called it after and idk if its correct or not. Therefore some clarification here would be great.

Section Upgrading your code with the mobx-undecorate codemod:

  • I dont understand this section at all, what is the goal here? As not english native speaker I would welcome any assistance through that part.
  • OR I understand it and it doens make any sense, If that section refers to removing decoratrs, why did I put everywhere in my code makeObservable(this)? Can anyone throw some light into this please?

ANYWAY as I said, I really apreciate your work, its jsut frustrating to work on something which is not a mainstream wave, therefore very limited google results.

at one place, like so?

Yes this configuration is global. Typically you would put it somewhere at the beginning (index.js/main.js). Technically you can call it anytime you want and it just changes the current configuration, so it's respected by any code/calls that follows the configure call.

Is it before calling a super() or after?

Try to place it before, you will get a JS syntax error.

where should I put the calling of makeObservable(this);

makeObservable(this) makes existing fields observable. Meaning you have to place it after all fields are defined and before anything that relies on obserability:

class A {
   a = 'a'
   constructor() {
      this.b = 'introducing new field inside a constructor';  // Since you use field initializers + decorators, you don't have to worry about this
      makeObservable(this, { a: observable, b: observable });
      // autorun/reaction/observe/intercept etc must be after
      autorun(() => console.log(this.a, this.b))
   }
}

mobx-undecorate codemod

It's a CLI tool that transforms your source code like this:

// original code
class A {
  @observable
   x = 0
}

// with --keepDecorators option
class A {
  @observable
   x = 0
   constructor() {
      makeObservable(this)
   }
}
// without --keepDecorators option
class A {
   x = 0
   constructor() {
      makeObservable(this, { x: observable })
   }
}

@urugator Thanks for quick reply. I will try to apply all your recommendations today, to see if it helps.

Is it before calling a super() or after?

Try to place it before, you will get a JS syntax error.

is that a recommendation, or are you encouraging me to try it out so I can see the error?

One more thing, I am not sure, where shoudl I put this line of code: ["@babel/plugin-proposal-class-properties", { "loose": false }]

We use craco instead of webpack and there are no signs of babel in our porject,m except peer dependecies. Shall I ignore that settings or do I have to write it somewhere? If so, where should I put it.

Many thanks

encouraging me to try it out so I can see the error?

https://craco.js.org/docs/configuration/babel/

@urugator So this piece of code is not correct?

export default class EditBundleViewModel extends ScreenBase {
	busyWatcher = new BusyWatcher();

	@observable searchId = 0;
	@observable searchText = "";
	@observable categories: Category[] = [];
	@observable upsells: Item[] = [];
	@observable selected: Item[] = [];
	@observable serverValidationErrors?: InvalidFields[];
	
	@observable itemsInBundle: OfferItemDto[] = [];
	@observable itemsInBundleExpanded: boolean[] = [];
	@observable itemsInAdditionalBundle: Item[] = [];
	@observable additionalBundleExpandedState: boolean[] = [];

	@observable fetchingItems = false;
	@observable fetchingUpsells = true;
	@observable deletableItems: ProductItemDto[] = [];
	@observable showNotSortedCategory = true;

	constructor(
		public context: OfferContext,
		public defaultExpanded: boolean,
		public localization: ILocalizationService,
		public dialogService: ConfirmDialogService,
		private otnaWiseporterRepository: OtnaWiseporterRepository,
		private otnaOfferItemsRepository: OtnaOfferItemsRepository,
		private editBundleService: EditBundleService,
		private userContext: UserContext,
		private notificationService: INotificationService
	) {
		super();
		makeObservable(this);
	}

and does the order matter? Like do I have to place makeObservable(this) frist and then call the mobx-undecorate?

It looks correct. You've added the makeObservable(this) to the constructor and you're basically done.
mobx-undecorate is just a tool so you don't have to do this by hand, but it does the same thing.
It's not something you call from the code, you call it from command line, it takes your .js/.ts files and modifies them.
Eg you have 180 classes, you either add makeObservable(this) to 180 constructors by hand or you run mobx-undecorate and it does it for you.

cool, looks like I successfully updated our app, Thanks for your support