jonataslaw / getx

Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
MIT License
10.43k stars 1.63k forks source link

[Flutter web] Hot Reload removes all routes except the current #843

Open dakr0013 opened 4 years ago

dakr0013 commented 4 years ago

Describe the bug If i use Get.toNamed() to navigate to other pages and do a hot reload all other pages get lost except the current page. Therefore if i try to navigate back (after a hot reload) i get to an empty page. Also if i use a controller of a previous page i get a null error after hot reloading. But if i use Navigator.pushNamed() and do a hot reload, my pages are still there and i can navigate back.

Reproduction code NOTE: THIS IS MANDATORY, IF YOUR ISSUE DOES NOT CONTAIN IT, IT WILL BE CLOSED PRELIMINARY)

example:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(GetMyApp());
  // runApp(MyApp());
  print("app started");
}

// ----------------------------------------------------------------------------
// navigation with flutters Navigator.pushNamed(...)
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: {
        "/": (_) => LoginPage(),
        "/register": (_) => RegisterPage(),
      },
      initialRoute: "/",
      navigatorObservers: [
        MyNavigatorObserver(),
      ],
    );
  }
}

class MyNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    print("navigated to: ${route.settings.name}");
  }
}

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("login"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("register"),
          onPressed: () => Navigator.pushNamed(context, "/register"),
        ),
      ),
    );
  }
}

class RegisterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("register"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("back"),
          onPressed: () => Navigator.pop(context),
        ),
      ),
    );
  }
}

// ----------------------------------------------------------------------------
// navigation with gets Get.toNamed(...)
class GetMyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Get Demo',
      getPages: [
        GetPage(
          name: "/",
          page: () => GetLoginPage(),
        ),
        GetPage(
          name: "/register",
          page: () => GetRegisterPage(),
        ),
      ],
      initialRoute: "/",
      navigatorObservers: [
        MyNavigatorObserver(),
      ],
    );
  }
}

class GetLoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("login"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("register"),
          onPressed: () => Get.toNamed("/register"),
        ),
      ),
    );
  }
}

class GetRegisterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("register"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("back"),
          onPressed: () => Get.back(),
        ),
      ),
    );
  }
}

To Reproduce Steps to reproduce the behavior:

  1. Run app on google chrome
  2. Click on 'register'
  3. Hot reload
  4. Click on 'back'

Expected behavior If i navigate through some routes and hot reload my app, i should be able to go back to a previous route, like with flutters navigator.

Flutter Version: Flutter 1.24.0-10.2.pre • channel beta

Getx Version: 3.21.2

Describe on which device you found the bug: Google Chrome Version 87.0.4280.66

Minimal reproduce code

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(GetMyApp());
}

class GetMyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Get Demo',
      getPages: [
        GetPage(
          name: "/",
          page: () => GetLoginPage(),
        ),
        GetPage(
          name: "/register",
          page: () => GetRegisterPage(),
        ),
      ],
      initialRoute: "/",
      navigatorObservers: [
        MyNavigatorObserver(),
      ],
    );
  }
}

class GetLoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("login"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("register"),
          onPressed: () => Get.toNamed("/register"),
        ),
      ),
    );
  }
}

class GetRegisterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("register"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("back"),
          onPressed: () => Get.back(),
        ),
      ),
    );
  }
}
jonataslaw commented 4 years ago

Unfortunately this is a recurring problem with Flutter web, all variables are cleared in the hotreload (not just those related to navigation), and for this reason their controllers are being destroyed. We could implement some feature to get around this in the routes, easily, but it would still affect controllers. You can see the related problem here:

https://github.com/flutter/flutter/issues/59277

dakr0013 commented 4 years ago

But if i use Navigator.pushNamed and MaterialApp the navigation stack does not get lost (see example). On hot reload, all pages get pushed on the stack again (you can see it in the console). If GetMaterialApp with Get.toNamed had the same behavior it could solve my problem. i am using bindings, so pushing the previous routes would create the controllers again.

hatemragab commented 2 years ago

Is there updates here?

Peshawa-k-kamil commented 2 years ago

any update ?

altafkhan8719 commented 1 year ago

I am also facing the same issue, on the refresh screen from the chrome web browser, it removes the controller.

rajeshbdabhi commented 1 year ago

any updates?

sinnoorc commented 1 year ago

am also facing same issue

Messhias commented 1 year ago

Waiting for update too.

SnowyTusk commented 1 year ago

Same.

wildsurfer commented 12 months ago

+1

MenaRaafat commented 11 months ago

Same, GetX needs this feature to fully support the web, else the refresh button causes a mess because it causes the app to hot reload. Also, the navigation stack is messed up if you click the browser's forward button after refreshing.

jonataslaw commented 11 months ago

I think it is definitely fixed in version 5

aditya-wappnet commented 10 months ago

In future this issue will be solved.

edrianolima commented 9 months ago

wainting for this fix

dhcracchiolo commented 8 months ago

Same here

Henriquek47 commented 6 months ago

Any updates?

jpedrosouza commented 5 months ago

So, hope is the last thing to die! Waiting for a fix too.

c-info commented 5 months ago

Any updates?

Surbhi2000312 commented 1 month ago

Hello, I'm not exactly a beginner, but I've been working for 5 to 6 years old flutter Project. This project used to work well with getX, but now I'm facing issues with the same project in a new repository provided by my boss. The problem is related to the state management on the web, and I've been struggling with it for a week. Do you have any suggestions on what to do?

Whenever get arguments call from home_landing page to home page I can reload the home landing page with no problem but any next page, if I reload then error occurs I am still confused why it is not saving in locally I tried a lot NoSuchMethodError: '[]' Dynamic call of null. Receiver : null Arguments: [0] See also: https://docs.flutter.dev/testing/errors

Home_landing page _getStart(String? rideType) { logEvent(rideType);

_homeController.allCityBooking(rideType??"");
// Get.toNamed(RoutersConst.home, arguments: [rideType]);

}

at Home Controller ` allCityBooking(String rideType) async { allCityRespo.value = ApiResponse.loading(); Get.dialog(showLoader(), barrierDismissible: false); final data = await _homeRepo.allCity(); // Get.back(); allCityRespo.value = data; Get.back();

if (allCityRespo.value.data!.statusCode == "1") {
  listDialogCity1(
      title: 'Select Your City',
      item: allCityRespo.value.data?.cityList,
      onPress: (int index) {

        city_id = allCityRespo.value.data!.cityList![index].id.toString();
        city_name = allCityRespo.value.data!.cityList![index].city.toString();

        print('cityyy $city_id $city_name $rideType');

        Get.toNamed(RoutersConst.home,
            arguments: [rideType,city_name,city_id]);
      });
} else {
  getSnackbar(
      title: StringConst.ERROR,
      subTitle: allCityRespo.value.data?.message??"",
      isSuccess: false);
}
return data;

}`

` DateTime addDay(String rideType) { DateTime now = DateTime.now(); if (rideType == StringConst.LONG) { //Add 3 days in Long term booking now = getDateTime(startDate.value).add(const Duration(days: 3, hours: 00)); endDate.value = getddMMyyyy(now); } else { endDate.value = getddMMyyyy(now); } openTime = 8; closeTime = 20; if(userInfo.value.officeOpenTime!.isNotEmpty){ openTime = getIntValueFromTime(userInfo.value.officeOpenTime!); closeTime = getIntValueFromTime(userInfo.value.officeCloseTime!);

}
// printLog(msg:"Close time openTime $openTime --  $closeTime ");
if((localEndTimer.hour)>=closeTime){
  localEndTimer = TimeOfDay.now().replace(hour: openTime+1, minute: 0, withoutMint: true);
  endDate.value = getddMMyyyy(now.add(const Duration(days: 1, hours: 00)));
  printLog(msg:"endDate.value localEndTimer $openTime $closeTime $localEndTimer   ${endDate.value}");
  endTime.value = localEndTimer.toString().substring(10, 15).toString();
}
if((localStartTimer.hour)<openTime) {
  localStartTimer = TimeOfDay.now().replace(hour: openTime, minute: 0, withoutMint: true);
  localEndTimer = TimeOfDay.now().replace(hour: openTime+1, minute: 0, withoutMint: true);
}
return now;

}`

`allCity() async { allCityRespo.value = ApiResponse.loading(); // Get.dialog(showLoader(), barrierDismissible: false); final data = await _homeRepo.allCity(); // Get.back(); allCityRespo.value = data; // Get.back();

/* if (allCityRespo.value.data.statusCode == "1") { listDialogCity( title: 'Select Your City', item: allCityRespo.value.data.cityList, onPress: (int index) { allCityReq.id = allCityRespo.value.data.cityList[index].id.toString();

       *//* Get.toNamed(RoutersConst.details,
            arguments: [jsonEncode(allVehicleReq), commonDate]);*//*
      });
} else {
  getSnackbar(
      title: StringConst.ERROR,
      subTitle: allCityRespo.value.data.message,
      isSuccess: false);
}*/

return data;

}`

HomePage `class HomePage extends GetView { final GlobalKey _scaffoldKey = GlobalKey(); final box = GetStorage(); var formKey = GlobalKey(); DateTime? startDateTime; DateTime? endDateTime; late BuildContext _ctx; var cityKey = GlobalKey(); // String customerId; final HomeController _homeController = Get.find(); TextEditingController cityCont = TextEditingController(); TextEditingController centerCont = TextEditingController(); var rideType = ''; String cityId = ''; String cityName = ''; String centerId = ''; AllVehicleReq? allVehicleReq; DateTime? _selectedDateTime;

@override Widget build(BuildContext context) { var argu = Get.arguments;

rideType = argu[0] ?? '';
cityName = argu[1] ?? '';
cityId = argu[2] ?? '';

_homeController.init();
_homeController.addDay(rideType ?? 'meow');

print(rideType);

print("argu.length : ${argu.length.toString()}");
// if (argu.length >= 2) Get.toNamed(argu[1]);
getVehicle(cityId);
_homeController.allCity();`

` void getVehicle(String city_idd) async {
logEvent("Search", map: {
  'Content Type': "Bike",
});
if (_homeController.endDate.value.contains('Select')) {
  getSnackbar(
      title: StringConst.ERROR,
      subTitle: 'Select end date and time',
      isSuccess: false);
} else {
  var userInfo = await _homeController.getUserInfo();
  allVehicleReq = AllVehicleReq();
  // sdfdsf
  allVehicleReq?.customerId = userInfo.customerId;
  allVehicleReq?.centerId = '';
  allVehicleReq?.cityId = city_idd;
  allVehicleReq?.fromDate = "${_homeController.startDate.value} ${_homeController.startTime.value}";
  allVehicleReq?.toDate =
  "${_homeController.endDate.value} ${_homeController.endTime.value}";
  allVehicleReq?.rideType = this.rideType;

  _homeController.allVehicle(allVehicleReq);
}

}`

amsyary commented 1 month ago

any update ? or any way to fix this?