rodydavis / signals.dart

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

The way of watching specific signal. #221

Closed snakeshift closed 3 months ago

snakeshift commented 3 months ago

Hi, I usually work with Vue.js and am new to flutter.

In the documentation, I saw that I can use effect to watch values, but is there anything that takes a specific value as an argument and can only detect when a value is entered there? In vue, effect is worth watchEffect, but I would like to have watch. https://vuejs.org/guide/essentials/watchers

Postscript, When I started learning flutter this time, I first learned statefulwidget and hooks + riverpod at first, but I found them too difficult to handle for me, so I ended up here. Signal is really great.Thank you!

rodydavis commented 3 months ago

Can give more of an example of what you are asking?

In flutter the listenSignal method which takes a context should do what you describe too but needs a context.

Effect can be used since it can subscribe to multiple signals at once. A signal can also expose its previousValue which can give you the same information as vue.js reactivity.

Happy to answer more questions, and welcome to signals!

snakeshift commented 3 months ago

Thanks for the reply, and sorry if it's rude as I'm translating in deepl. here is example.

final countA = signal(0);
final countB = signal(0);

effect(() {
  print(countA.value + countB.value); // 0 → 1 → 2
});

countA.value++;
countB.value++;

In this example, I have defined two signals, A and B, so that if we count up either of them, the sum of the signals will be printed.

However, if only B is counted up, how can we make sure that the sum of A and B is printed?

final countA = signal(0);
final countB = signal(0);

effect(() {
  print(countA.value + countB.value); // 2
});

countA.value++; // wont print
countB.value++; // only this

It is probably possible to print a count only for B by comparing the previousValue in the effect, However, since the effect itself fires, user must take care of that re-executing in effect.

In Vue, there are two functions, watch and watchEffect, As for watchEffect, I think it works almost completely the same as effect.

The difference is that watch track only the signals added to the argument array and does not execute the first time. (In fact, I think there are many cases where I want to fire effect only when value is changed, not the first time.)

thank you!

https://vuejs.org/guide/essentials/watchers#watch-vs-watcheffect

PS. Vue Example

watchEffect(() => {
  console.log(countA.value + countB.value); // 0, 1, 2
});

watch([countB], () => {
  console.log(countA.value + countB.value); // 2
});
rodydavis commented 3 months ago

Is there a reason you would not want to use a computed signal in this example?

Also for any signals you do not want to subscribe in the effect you can use .peek() and it will only track the ones that use .value

snakeshift commented 3 months ago

Sorry, maybe I did not sample well. What I am asking is if it is possible to control the firing timing of the effect.

final count = signal(0);

effect(() {
  print(‘called’);
});

count.value++;

I simply want this effect to fire when there is a change in count.value. Is there any way to catch this without including a signal, like adding an if within the effect?

In vue, I can do like this.

watch([count], () => {
  console.log('called');
});

count.value++;
jinyus commented 3 months ago

You could use count.subscribe() or use .peek() for the signals you don't want to trigger the effect.

effect(() => print(countA.value + countB.peek());

Or

countA.subscribe((v) => print(v + countB.value);
snakeshift commented 3 months ago

countA.subscribe((v) => print(v + countB.value);

This is exactly what I am looking for!! thank you all!