Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ViewModel: Function fields vs function literals? #214

Open
hacker1024 opened this issue Apr 5, 2021 · 2 comments
Open

ViewModel: Function fields vs function literals? #214

hacker1024 opened this issue Apr 5, 2021 · 2 comments

Comments

@hacker1024
Copy link

hacker1024 commented Apr 5, 2021

In many examples (including the TODO architecture sample), ViewModels are created like so:

class ViewModel {
  final void Function() myFunction;
  final String myProperty;

  ViewModel({
    required this.myFunction,
    required this.myProperty,
  });

  factory ViewModel.fromStore(Store<AppState> store) {
    return ViewModel(
      myFunction: () => store.dispatch(const MyFunctionAction()),
      myProperty: store.state.myProperty,
    );
  }
}

This (IMO) has the following problems

  • myFunction may be accidentally used in a == or hashCode implementation, which would be incorrect as the closure would be non-identical with every new ViewModel
  • More RAM usage (maybe?)

Why is that the recommended approach, compared to something like this?

class ViewModel {
  final Store<AppState> _store;

  ViewModel(this._store) : myProperty = _store.state.myProperty;

  final String myProperty;

  void myFunction() => _store.dispatch(const MyFunctionAction());
}
@brianegan
Copy link
Owner

brianegan commented Apr 6, 2021

Agreed -- your approach is a bit better for the reasons you state!

I was originally playing around with some ideas of creating the ViewModel more in the build function, where it's nice to be able to define those callback functions.

However, as I began to realize it's actually nicer to create the view Model in a static factory / normal class constructor, it now makes less sense.

@bigbn
Copy link

bigbn commented Jul 18, 2024

I'm using Equatable libaray for comparsion rules. The real-word example below:

class _StoreMediator extends Equatable {
  final String phoneNumber;
  final void Function() openAccountScreen;
  final void Function() openRegistrationScreen;

  @override
  List<Object?> get props => [phoneNumber];         //  <---

  const _StoreMediator(
      {required this.phoneNumber,
      required this.openAccountScreen,
      required this.openRegistrationScreen});

  static _StoreMediator connect(Store<RootState> store) {
    return _StoreMediator(
      phoneNumber: store.state.account.phoneNumber,
      openAccountScreen: () => store.dispatch(NavigateToAction('/account')),
      openRegistrationScreen: () => store.dispatch(NavigateToAction('/registration')),
    );
  }
}

this will ensure that only [phoneNumber] fields are compared

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants