mobxjs / mobx.dart

MobX for the Dart language. Hassle-free, reactive state-management for your Dart and Flutter apps.
https://mobx.netlify.app
MIT License
2.39k stars 310 forks source link

Inherit an store implementation acts like a kind of singleton #1000

Closed edcogue closed 1 month ago

edcogue commented 3 months ago

I want to use an Store implementation like this

import 'package:mobx/mobx.dart';
part 'parent_controller.g.dart';

abstract class ParentStore = _ParentStore
    with _$ParentStore;

abstract class _ParentStore with Store {
  @observable
  ObservableList<String> someInfoList = emptyList;

  static ObservableList<String> emptyList = ObservableList.of([]);

  @observable
  ObservableFuture<List<String>> fetchInfoFuture = emptyResponse;

  @computed
  bool get hasResults =>
      fetchInfoFuture != emptyResponse &&
          fetchInfoFuture.status == FutureStatus.fulfilled ||
      someInfoList.isNotEmpty;

  static ObservableFuture<List<String>> emptyResponse =
      ObservableFuture.value([]);

  @action
  Future<void> fetchAndFollow() async {
    if (fetchInfoFuture.status == FutureStatus.pending) return;

    final future = fetch();
    fetchInfoFuture = ObservableFuture(future);

    final newInfo = await future;

    newInfo.map((e) => someInfoList.add(e));
  }

  Future<List<String>> fetch();
}

To implement the remaining abstract method fetch this way in another controller to reuse the previous code

import 'package:test/parent_controller.dart';

class ChildStore extends ParentStore {
  SomeRepo repo =  SomeRepo();

  @override
  Future<List<String>> fetch() async {
    final info = await repo.getAll();
    return info;
  }
}
import 'package:test/parent_controller.dart';

class OtherChildStore extends ParentStore {

  @override
  Future<List<String>> fetch() async {
    return [];
  }
}

When I use the ChildStore and OtherChildStore with different fetch methods, it seems that the data is store in a singleton, because no matter which is the implementation of fetch, all provide the same data. Is it possible to achieve this behavior?

amondnet commented 1 month ago

@edcogue

This is likely because someInfoList has a static variable assigned to it.

  @observable
  ObservableList<String> someInfoList = emptyList; // static emptyList

  static ObservableList<String> emptyList = ObservableList.of([]);

=>

  @observable
  ObservableList<String> someInfoList = ObservableList.of([]);

Let me know if this doesn't work for you.