Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rebuildOnChange doesn't actually control rebuilding #124

Closed
ThinkDigitalSoftware opened this issue Apr 17, 2019 · 7 comments
Closed

rebuildOnChange doesn't actually control rebuilding #124

ThinkDigitalSoftware opened this issue Apr 17, 2019 · 7 comments

Comments

@ThinkDigitalSoftware
Copy link

ThinkDigitalSoftware commented Apr 17, 2019

No matter what I put in this value, it always rebuilds. As you can see in the below photo, the expression evaluated to false, yet I'm paused on a breakpoint in the builder and it's not the first build.
Screen Shot 2019-04-16 at 6 48 33 PM

@RedBrogdon
Copy link

Can't see enough of the code to know, but is it possible the StoreBuilder itself is getting rebuilt from somewhere higher in the tree?

Try creating a super stripped-down example and see if you can replicate the issue.

@ThinkDigitalSoftware
Copy link
Author

ThinkDigitalSoftware commented Apr 19, 2019 via email

@ThinkDigitalSoftware
Copy link
Author

ThinkDigitalSoftware commented Apr 19, 2019

@brianegan https://github.com/ThinkDigitalRepair/redux_rebuild_on_change_test
here you go. It's your Redux Counter example. I just added the line
rebuildOnChange: false,
to the StoreConnector that surrounds the counter text and the app continues to work as normal.

@brianegan
Copy link
Owner

Hrm, this is odd. When I change rebuildOnChange to false, the builder function is not run when using the StoreBuilder or StoreConnector Widgets, and I have tests that verify this behavior as well.

Do either of these work for ya, or do they both rebuild on your machine?

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

/// Define the actions available to this app
enum Actions {
  /// Listen for this action to increment the count
  increment,
}

/// The reducer, which takes the previous count and increments it in response
/// to an Increment action.
int counterReducer(int state, dynamic action) {
  if (action == Actions.increment) {
    return state + 1;
  }

  return state;
}

void main() {
  // Create your store as a final variable in a base Widget. This works better
  // with Hot Reload than creating it directly in the `build` function.
  final store = Store<int>(counterReducer, initialState: 0);

  runApp(FlutterReduxApp(
    title: 'Flutter Redux Demo',
    store: store,
  ));
}

/// The Application Widget
class FlutterReduxApp extends StatelessWidget {
  /// The Redux Store
  final Store<int> store;

  /// The title of the app
  final String title;

  /// Constructor for the application Widget
  FlutterReduxApp({Key key, this.store, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // The StoreProvider should wrap your MaterialApp or WidgetsApp. This will
    // ensure all routes have access to the store.
    return StoreProvider<int>(
      // Pass the store to the StoreProvider. Any ancestor `StoreConnector`
      // Widgets will find and use this value as the `Store`.
      store: store,
      child: MaterialApp(
        theme: ThemeData.dark(),
        title: title,
        home: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text('You have pushed the button this many times:'),
                // Connect the Store to a Text Widget that renders the current
                // count.
                //
                // We'll wrap the Text Widget in a `StoreConnector` Widget. The
                // `StoreConnector` will find the `Store` from the nearest
                // `StoreProvider` ancestor, convert it into a String of the
                // latest count, and pass that String  to the `builder` function
                // as the `count`.
                //
                // Every time the button is tapped, an action is dispatched and
                // run through the reducer. After the reducer updates the state,
                // the Widget will be automatically rebuilt with the latest
                // count. No need to manually manage subscriptions or Streams!
                StoreBuilder<int>(
                  rebuildOnChange: false,
                  builder: (context, store) {
                    print('${DateTime.now()} building');
                    return Text(
                      '${store.state}',
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                )
              ],
            ),
          ),
          // Connect the Store to a FloatingActionButton. In this case, we'll
          // use the Store to build a callback that with dispatch an Increment
          // Action.
          //
          // Then, we'll pass this callback to the button's `onPressed` handler.
          floatingActionButton: StoreConnector<int, VoidCallback>(
            converter: (store) {
              // Return a `VoidCallback`, which is a fancy name for a function
              // with no parameters. It only dispatches an Increment action.
              return () => store.dispatch(Actions.increment);
            },
            builder: (context, callback) {
              return FloatingActionButton(
                // Attach the `callback` to the `onPressed` attribute
                onPressed: callback,
                tooltip: 'asdasdasd',
                child: const Icon(Icons.add),
              );
            },
          ),
        ),
      ),
    );
  }
}

or

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

/// Define the actions available to this app
enum Actions {
  /// Listen for this action to increment the count
  increment,
}

/// The reducer, which takes the previous count and increments it in response
/// to an Increment action.
int counterReducer(int state, dynamic action) {
  if (action == Actions.increment) {
    return state + 1;
  }

  return state;
}

void main() {
  // Create your store as a final variable in a base Widget. This works better
  // with Hot Reload than creating it directly in the `build` function.
  final store = Store<int>(counterReducer, initialState: 0);

  runApp(FlutterReduxApp(
    title: 'Flutter Redux Demo',
    store: store,
  ));
}

/// The Application Widget
class FlutterReduxApp extends StatelessWidget {
  /// The Redux Store
  final Store<int> store;

  /// The title of the app
  final String title;

  /// Constructor for the application Widget
  FlutterReduxApp({Key key, this.store, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // The StoreProvider should wrap your MaterialApp or WidgetsApp. This will
    // ensure all routes have access to the store.
    return StoreProvider<int>(
      // Pass the store to the StoreProvider. Any ancestor `StoreConnector`
      // Widgets will find and use this value as the `Store`.
      store: store,
      child: MaterialApp(
        theme: ThemeData.dark(),
        title: title,
        home: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text('You have pushed the button this many times:'),
                // Connect the Store to a Text Widget that renders the current
                // count.
                //
                // We'll wrap the Text Widget in a `StoreConnector` Widget. The
                // `StoreConnector` will find the `Store` from the nearest
                // `StoreProvider` ancestor, convert it into a String of the
                // latest count, and pass that String  to the `builder` function
                // as the `count`.
                //
                // Every time the button is tapped, an action is dispatched and
                // run through the reducer. After the reducer updates the state,
                // the Widget will be automatically rebuilt with the latest
                // count. No need to manually manage subscriptions or Streams!
                StoreConnector<int, String>(
                  rebuildOnChange: false,
                  converter: (store) => '${store.state}',
                  builder: (context, count) {
                    print('${DateTime.now()} building');
                    return Text(
                      count,
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                )
              ],
            ),
          ),
          // Connect the Store to a FloatingActionButton. In this case, we'll
          // use the Store to build a callback that with dispatch an Increment
          // Action.
          //
          // Then, we'll pass this callback to the button's `onPressed` handler.
          floatingActionButton: StoreConnector<int, VoidCallback>(
            converter: (store) {
              // Return a `VoidCallback`, which is a fancy name for a function
              // with no parameters. It only dispatches an Increment action.
              return () => store.dispatch(Actions.increment);
            },
            builder: (context, callback) {
              return FloatingActionButton(
                // Attach the `callback` to the `onPressed` attribute
                onPressed: callback,
                tooltip: 'asdasdasd',
                child: const Icon(Icons.add),
              );
            },
          ),
        ),
      ),
    );
  }
}

@ThinkDigitalSoftware
Copy link
Author

Sorry, I didn't see your response until now. Checking

@ThinkDigitalSoftware
Copy link
Author

ThinkDigitalSoftware commented Apr 25, 2019

Neither example rebuilt when the button was tapped. I wonder what's different. Did you run my project?

@ThinkDigitalSoftware
Copy link
Author

ThinkDigitalSoftware commented Apr 25, 2019

It's ALL working now.............., even with my example...
I have no way to explain that....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants