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.4k stars 310 forks source link

Changing a value of certain index in ObservableList of tubles makes some issues #1015

Open WissamALSbenaty opened 2 months ago

WissamALSbenaty commented 2 months ago

I have this example

mixin MultipleImagePickingMixin on BaseController {
  @observable
  ObservableList<(FileDto?,ImageModel?)> images = ObservableList.of([(null,null)]);
  @action
  void increaseImagesCounter() => images.add((null,null));
  @action
  void removeImage({required final int imageIndex}) =>
      imageIndex == 0 && images.length == 1
          ? () {}
          : images.removeAt(imageIndex);
  @action
  void changeImage(
          {required final int index, required final FileDto newImage}) =>
      images[index] = (newImage,null);
}

Where BaseController is a Store

When i try to change an image , an exception is thrown Unhandled Exception: type '(FileDto, Null)' is not a subtype of type '(Null, Null)' of 'value'

WissamALSbenaty commented 2 months ago

It turns out that the problem is from using a nullable generic type which is not supported for ObservableList functions like operator [] , add , insert , etc

so if you trying to use ObservableList<Something?> then all functions mentioned above of this instance should use a Something object not Something?

amondnet commented 2 weeks ago

@WissamALSbenaty

The test code below succeeds. Can you share a reproducible repository?

import 'package:mobx/mobx.dart';

part 'meta.g.dart';

class Meta extends _Meta with _$Meta {
  Meta();
}

abstract class _Meta with Store {
  @observable
  ObservableList<(String?,String?)> images = ObservableList.of([(null,null)]);
  @action
  void increaseImagesCounter() => images.add((null,null));
  @action
  void removeImage({required final int imageIndex}) =>
      imageIndex == 0 && images.length == 1
          ? () {}
          : images.removeAt(imageIndex);
  @action
  void changeImage(
      {required final int index, required final String newImage}) =>
      images[index] = (newImage,null);
}
import 'package:untitled/meta.dart';
import 'package:test/test.dart';

void main() {

  test('changeImage does not throw an error', () {
    var store = Meta();
    store.increaseImagesCounter();
    expect(() => store.changeImage(index: 0, newImage: "test"), returnsNormally);
  });

  test('observable list', () {
    var list = ObservableList<int?>();
    expect(() => list.add(null), returnsNormally);
    expect(() => list.insert(0, null), returnsNormally);
    expect(() => list[0] = 1, returnsNormally);
  });
}