data_state_mobx 0.1.0 copy "data_state_mobx: ^0.1.0" to clipboard
data_state_mobx: ^0.1.0 copied to clipboard

A powerful state machine for MobX management, which can be used in almost any application state.

A powerful state machine for MobX management, which can be used in almost any application state.

It has 3 states - loading, success, error - and is perfect to be used on infinite lists, action buttons, with shimmers, refresh logic, etc.

Requirements #

This package just works with the MobX. And minimum Dart SDK 2.16.

Getting started #

Basically you can switch between the three states to control your data.

On data loading, call:

dataState.setLoadingState();

On get data successfully:

dataState.setSuccessState(data);

On get an error:

dataState.setErrorState(error);

And the DataState will handle the rest.

To deal with the widgets on each state, you can listen the state - or the computed getters isLoading, isSuccess, isError - at your Observer widget, for example:

Observer(
  builder: (_) => ElevatedButton(
    child: controller.loginState.isLoading
        ? const CircularProgressIndicator()
        : const Text('Button'),
    onPressed: () {},
  ),
)

Or you can use the features below.

Features #

Simple states #

To deal with simple logics, like showing a list of strings.

Crate the DataState on the mobx controller file:

final dataState = DataState<List<String>>();

Future<void> fetchData() async {
  dataState.setLoadingState();

  try {
    final data = await Future.delayed(const Duration(seconds: 3))
        .then((_) => ['String 1', 'String 2', 'String 3']);
    dataState.setSuccessState(data);
  } catch (e) {
    dataState.setErrorState(e);
  }
}

Then add on your view the Observer to present the list:

final controller = ControllerInstance();

@override
void initState() {
  fetchData();
  //...
  super.initState();
}

@override
Widget build(context) {
  //...
  Observer(
    builder: (context) => controller.dataState.handleState(
      loading: () {
        return const CircularProgressIndicator();
      },
      success: (data) {
        return ListView.builder(
          shrinkWrap: true,
          itemCount: data.length,
          itemBuilder: (context, index) => Text(
            data[index],
            textAlign: TextAlign.center,
          ),
        );
      },
      error: (error) {
        return const Text('Error');
      },
    ),
  ),
}

See the full code here.

Reloadable states #

Use the handleStateLoadableWithData method when you want to use data on the loading widget callback. On an infinite list or refresh logic for example.

Observer(
  builder: (context) => controller.dataState.handleStateLoadableWithData(
    loading: (data) {
      return Stack(
        children: [
          if (data != null) list(data),
          Positioned.fill(
            child: Container(
              color: Colors.black45,
              alignment: Alignment.center,
              child: const CircularProgressIndicator()),
          ),
        ],
      );
    },
    success: (data) => list(data),
    error: (error) {
      return const Text('Error');
    },
  ),
);

See the full example code here.

States using reaction #

To handle states only once after it changes, the handleReactionState is the solution. Just set it on the initState and remember to dispose it on the dispose method.

For example, to show a full dialog:

List<ReactionDisposer>? reactionsDisposers;

@override
void initState() {
  reactionsDisposers = [
    controller.dataState.handleReactionState(
      loading: loadingDialog,
    )
  ];
  super.initState();
}

@override
void dispose() {
  reactionsDisposers?.forEach((dispose) {
    dispose();
  });
  super.dispose();
}

void loadingDialog(bool show) {
  if (show) {
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) {
        return Dialog(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                CircularProgressIndicator(),
                SizedBox(width: 32),
                Text("Loading"),
              ],
            ),
          ),
        );
      },
    );
  } else {
    Navigator.of(context).pop();
  }
}

See the full example code here.

7
likes
130
pub points
52%
popularity

Publisher

unverified uploader

A powerful state machine for MobX management, which can be used in almost any application state.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (LICENSE)

Dependencies

flutter, mobx

More

Packages that depend on data_state_mobx