rodydavis / signals.dart

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

Weird behavior in stateless widget #155

Closed nowfalsalahudeen closed 9 months ago

nowfalsalahudeen commented 9 months ago

I tried signals in a stateless widget

The watch is not updating the UI. If I add another watch with the same signal variable, it rebuilds the first one only. Why does this happen, but in the case of StatefulWidget, it's working fine

Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          controller.increment();
          print('incremented counter value: ${controller.counter.value}');
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Watch(
              (context) => Text('You have pushed the button this many times: ${controller.counter.value}'),
            ),
            Watch.builder(
              builder: (context) {
                return Text('test => ${controller.counter.value}');
              }
            ),
            Watch((context) {
              return Text(
                'You have pushed the button this many times: ${controller.counter.value}',
                style: Theme.of(context).textTheme.headlineMedium!,
              );
            }),
          ],
        ),
      ),
    );`
```

`class CounterController {

var counter = signal(0); void increment() => counter.value++; }`

nowfalsalahudeen commented 9 months ago

it runs when force restart the app (stop the app and run it again), not working with hot reload after some changes, every time it needs to be manully restart the app

rodydavis commented 9 months ago

So the hot reload might be changing the element id, but will see if I can write some tests to validate.

Can you create a minimal example to link to for testing? Or provide the complete code working and non working in the issue?

nowfalsalahudeen commented 9 months ago
import 'package:flutter/material.dart';
import 'package:signals/signals_flutter.dart';

import 'counter_controller.dart';

class CounterPage extends StatelessWidget {
  CounterPage({super.key});

  final controller = CounterController();

  @override
  Widget build(BuildContext context) {
    // var state = controller.counter.watch(context);
    print('rebuild state');
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          controller.increment();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Watch((context) {
              print('rebuild watch controller');
              return Text('You have pushed the button this many times: ${controller.counter}');
            }),
          ],
        ),
      ),
    );
  }
}

import 'package:signals/signals.dart';

class CounterController  {

  var counter = signal(0);

  void increment() => counter.value++;

}

This is the code. If anything changes, then hot reload it. After that, it won't update the UI until I stop and rerun the app

but if i change StatelessWidget to StatefullWidget , its working fine as expected

rodydavis commented 9 months ago

Looking into it!

nowfalsalahudeen commented 9 months ago

And one more thing: if it's working after rerunning the app, when I hot reload again, it loses the state of the signal (e.g., the counter integer resets to its initial state). This behavior doesn't happen in other state management libraries like Riverpod and GetX.

However, in stateful widgets, it's absolutely fine. We need this behavior in stateless widgets too.

I really like the concept of this state management. The primary goal is to spin up the app very quickly, and not using the generator is actually a good move. I'm fed up with Riverpod, Provider, MobX - most of them need to run build_runner to generate their classes. That's why GetX has huge popularity; it's straightforward.

rodydavis commented 9 months ago

Was able to reproduce, working on the fix!

rodydavis commented 9 months ago

Fixed on 4.2.1!

nowfalsalahudeen commented 9 months ago

It's working fine. But in the case of the stateless widget, it does not persist the state when hot-reload.

I think its a bug because most of the statemanagemnt libs handle this well even in stateless or stateful widgets

nowfalsalahudeen commented 9 months ago

@rodydavis please take a look on to it

rodydavis commented 9 months ago

That is because it is not created with const or static. If you add the static keyword to the controller declaration it will persist state

nowfalsalahudeen commented 9 months ago

Its working. thankyou

can you make a cli for create controller, view

rodydavis commented 9 months ago
import 'package:flutter/material.dart';
import 'package:signals/signals_flutter.dart';

import 'counter_controller.dart';

class CounterPage extends StatelessWidget {
  CounterPage({super.key});

-  final controller = CounterController();
+  static final controller = CounterController();

  @override
  Widget build(BuildContext context) {
    // var state = controller.counter.watch(context);
    print('rebuild state');
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          controller.increment();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Watch((context) {
              print('rebuild watch controller');
              return Text('You have pushed the button this many times: ${controller.counter}');
            }),
          ],
        ),
      ),
    );
  }
}
rodydavis commented 9 months ago

Can you open a new discussion or issue about a CLI or Code Snippets?

nowfalsalahudeen commented 9 months ago

yes

On Mon, 12 Feb, 2024, 12:49 pm Rody Davis, @.***> wrote:

Can you open a new discussion or issue about a CLI or Code Snippets?

— Reply to this email directly, view it on GitHub https://github.com/rodydavis/signals.dart/issues/155#issuecomment-1938340330, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABAQO3NW3QJBRBDACYZ4C4LYTHQUJAVCNFSM6AAAAABC5LD6L2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZYGM2DAMZTGA . You are receiving this because you authored the thread.Message ID: @.***>