Skip to content

A simple state management library for Flutter based on States and Actions managed by Streams with RxDart.

License

Notifications You must be signed in to change notification settings

alvarobcprado/re_state_action

Repository files navigation

Re:StateAction

Pub.dev Badge GitHub Build Badge MIT License Badge Very Good Analysis Style Badge

About

This package acts as a wrapper for the popular [RxDart] library, simplifying state management through streams. It offers a straightforward solution to effectively handle application state and seamlessly manage interactions between the user interface (UI) and the user. By leveraging the package's reactive approach, you can efficiently handle UI components such as dialogs, alerts, modals, and more, all while avoiding unnecessary state overload.

Usage

To create a simple ReStateAction class:

abstract class ShowSnackbarAction{}

class ShowIsEvenValueSnackbarAction extends ShowSnackbarAction{}

class CounterStateAction extends ReStateAction<int, ShowSnackbarAction> {
  CounterStateAction({int initialState = 0}) : super(initialState){
    // Here you can add the listeners to the state
    listenState((state){
        if(state.isEven){
         emitAction(ShowIsEvenValueSnackbarAction());
        }
    });
  }

  void increment() => emitState(state + 1);
  void decrement() => emitState(state - 1);
}

In this example, we utilize the package to create a CounterStateAction class, responsible for managing the state of a counter by extending the ReStateAction class.

Within the class constructor, a listener is set up to monitor state changes. When the state becomes even, an action of type ShowIsEvenValueSnackbarAction is emitted using the emitAction method. This allows you to handle the event and display a snackbar or perform other actions as needed.

When using to manage simple states, instead to use the [ReStateAction] class, we can use the [ReState] class. It is a simple class that manages the state of your application. It is useful when you don't need to manage the interaction between the UI and the user.

To create a simple [ReState] class:

class CounterReState extends ReState<int> {
  CounterReState({int initialState = 0}) : super(initialState);

  void increment() => emitState(state + 1);
  void decrement() => emitState(state - 1);
}

We can access the state using the [state] getter or accessing the stream using the [stateStream] getter. The actions are accessed only using the [actionStream] property. Both state and actions are streams and can be listened using the [listenState] and [listenAction] methods.

To use the [ReState] class in the UI, we can use the [ReStateWidget]. It is a widget that rebuilds the UI when the state changes.

ReStateWidget<int>(
  reState: counterReState,
  builder: (context, state) {
    return Text('$state');
  },
),

To use the [ReStateAction] class in the UI, we can use the [ReStateActionWidget]. It is a widget that rebuilds the UI when the state changes and also listens to the actions.

ReStateActionWidget<int, ShowSnackbarAction>(
  reState: counterReStateAction,
  onAction: (action) {
    if (action is ShowIsEvenValueSnackbarAction) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('The value is even'),
        ),
      );
    }
  },
  builder: (context, state, child) {
    return Column(
      children: [
        Text('Current value: $state'),
        TextButton(
          onPressed: () => counterReStateAction.increment(),
          child: Text('Increment'),
        ),
        TextButton(
          onPressed: () => counterReStateAction.decrement(),
          child: Text('Decrement'),
        ),
      ],
    );
  },
),

If we need only to listen to the actions, we can use the [ReActionListener] widget.

ReActionListener<ShowSnackbarAction>(
  reState: counterStateAction,
  onAction: (action) {
    if (action is ShowIsEvenValueSnackbarAction) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('The value is even'),
        ),
      );
    }
  },
  child: Text('Widget that will not be rebuilt'),
),

Dart 3.0

The package is compatible with Dart 3.0 new features like sealed classes and pattern matching. To use it, you need to update your Flutter version to 3.10.0 or above and enable the Dart 3.0 features in your pubspec.yaml file.

environment:
  sdk: ">=3.0.0 <4.0.0"

An usecase example:

sealed class ShowSnackbarAction{}

class ShowIsEvenValueSnackbarAction extends ShowSnackbarAction{}

class ShowIsOddValueSnackbarAction extends ShowSnackbarAction{}

class CounterStateAction extends ReStateAction<int, ShowSnackbarAction> {
  CounterStateAction({int initialState = 0}) : super(initialState){
    // Here you can add the listeners to the state
    listenState((state){
        if(state.isEven){
         emitAction(ShowIsEvenValueSnackbarAction());
        }else{
         emitAction(ShowIsOddValueSnackbarAction());
        }
    });
  }

  void increment() => emitState(state + 1);
  void decrement() => emitState(state - 1);
}

//... in the UI
ReActionListener<ShowSnackbarAction>(
  reState: counterStateAction,
  onAction: (action) {
    final snackbarText = switch (action) {
          ShowIsEvenValueSnackbarAction() => 'The value is even',
          ShowIsOddValueSnackbarAction() => 'The value is odd',
          _ => 'The value is null',
        };
    
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(snackbarText),
      ),
    );
  },
  child: Text('Widget that will not be rebuilt'),
),

Example

To see a complete example, see the ReStateAction Example folder.

Contributing

We welcome contributions to this package. If you would like to contribute, please feel free to open an issue or a pull request.

License

ReStateAction is licensed under the MIT License. See the LICENSE for details.

About

A simple state management library for Flutter based on States and Actions managed by Streams with RxDart.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published