rodydavis / signals.dart

Reactive programming made simple for Dart and Flutter
http://dartsignals.dev
Apache License 2.0
378 stars 44 forks source link

Computed.overrideWith computes previous value before override value #262

Closed rizumita closed 2 months ago

rizumita commented 2 months ago

Computed.overrideWith executes this._reset(value), which updates _value after the existing _fn of Computed is executed, resulting in the generation of the value before the change.

Is this the correct behavior?

When overriding with a mock in tests, it is initialized with the regular value, which is not the expected behavior.

rodydavis commented 2 months ago

Do you have a test code sample to share for expected behavior?

rizumita commented 2 months ago

Create this computed.

final count = computed(() {
  print('Computed called');
  return 1;
});

Run this test.

void main() {
  test('count', () {
    count.overrideWith(2);
    expect(count.value, 2);
  });
}

'Computed called' is displayed, and the test succeeds. I want to override the initial implementation of computed without executing it.

rodydavis commented 2 months ago

This is interesting, there was an issue where others thought it should trigger a subscription when overridden.

As for deciding the correct behavior, this should be like you describe as it should not execute the callback when overriding.

rizumita commented 2 months ago

I am managing FirebaseAuth with Computed. The reason is to override FirebaseAuth with a mock in unit tests. If I manage it with Signal, it will create an instance of FirebaseAuth, which causes errors in unit tests. Therefore, I decided to manage it with Computed. However, due to the behavior of Computed reported in this issue, the same problem occurred even with Computed. If Computed cannot be used, I think the alternative would be to manage it with Signal using FirebaseAuth Function(). Alternatively, it might be good if there is a class like LazySignal.

rodydavis commented 2 months ago

I am going to work on the patch.

another approach would be to update a signal instead of computed. If it is never read it will not update.

meaning .value instead of .override