I want to write the ReactionBuilder with Mobx, which will check a connection with my server periodicly and do new request to connect it if there is not a connection. How can I do it correctly?
I have the next state class of a page which contains a function to test connection with my backend server:
abstract class LandingPageStateBase with Store {
final IempServerRepositoryBase _iempServerRepository;
var counterTryToConnect = 0;
...
@observable
bool isLoading = false;
...
@action
Future<void> getTestConnection() async {
counterTryToConnect += 1;
isLoading = true;
connection = null;
try {
final data = await _iempServerRepository.getConnection();
connection = data;
} on Exception catch (_) {
connection = null;
}
isLoading = false;
}
bool isConnected() {
return connection != null && !isLoading;
}
}
And a part of widget page:
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: SafeArea(
child: ReactionBuilder(
builder: (context) {
_landingPageState.getTestConnection();
// HERE I NEED TO CHECK CONNECTION AND DO IT AGAIN IF NOT CONNECTED
return reaction((_) => _landingPageState.isLoading, (_) {
if (!_landingPageState.isConnected() &&
_landingPageState.counterTryToConnect < 4) {
_landingPageState.getTestConnection();
} else if (_landingPageState.isConnected()) {
Future.delayed(const Duration(milliseconds: 500), () {
setState(() {
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (context) => const LogInPage()));
});
});
}
debugPrint('debug: ${_landingPageState.counterTryToConnect}');
}, delay: 1000);
},
...
I don't consider options using Stream, because I use the concept of working with Mobx and do not want to mix different approaches with reactivity. I just wanna understand how I can do it with Mobx.
I solved the problem the next way:
abstract class LandingPageStateBase with Store {
final IempServerRepositoryBase _iempServerRepository;
LandingPageStateBase(this._iempServerRepository);
final _maxRetryToConnectCount = 10;
int retryToConnectCount = 0;
Connection? connection;
@observable
ConnectionState connectionState = ConnectionState.waiting;
@action
Future<void> connectToServer() async {
connectionState = ConnectionState.waiting;
try {
final data = await _iempServerRepository.getConnection();
connection = data;
connectionState = ConnectionState.done;
} catch (_) {}
if (connectionState == ConnectionState.done) {
retryToConnectCount = 0;
} else {
retryToConnectCount++;
if (retryToConnectCount < _maxRetryToConnectCount) {
await Future.delayed(const Duration(seconds: 2));
connectToServer();
} else {
connectionState = ConnectionState.none;
}
}
}
}
And the page's widget:
child: ReactionBuilder(
builder: (context) {
_landingPageState.connectToServer();
return reaction((_) => _landingPageState.connectionState, (_) {
if (_landingPageState.connectionState == ConnectionState.done) {
Future.delayed(const Duration(milliseconds: 500), () {
setState(() {
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (context) => const LogInPage()));
});
});
}
debugPrint('debug: ${_landingPageState.connectionState.name}');
}, delay: 2000);
},