Home > Enterprise >  Flutter GetX Obx [Get] the improper use of a GetX has been detected. You should only use GetX or Obx
Flutter GetX Obx [Get] the improper use of a GetX has been detected. You should only use GetX or Obx

Time:11-25

I am using GetX and heavily using Obx to build by UI in a reactive way, however, I've always stumbled whenever I need to do some processing of my Rx-variables and it ended up with this error:

      [Get] the improper use of a GetX has been detected.
      You should only use GetX or Obx for the specific widget that will be updated.
      If you are seeing this error, you probably did not insert any observable variables into GetX/Obx
      or insert them outside the scope that GetX considers suitable for an update
      (example: GetX => HeavyWidget => variableObservable).
      If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.

My Widget build() function looks like this:

    // class ProductDetailScreen extends GetWidget<ProductDetailScreenController>
    // late final CartListController _cartListController =
          Get.find<CartListController>();
    // ..

    Widget build(BuildContext context) {
        RxProductData data = controller.productData;
        _cartItemModel = _cartListController.rxCart.getItem(data.id); // 2. I need widget to rebuild whenever rxCart changed, since the _cartItemModel returned might have changed. (eg: _cartItemModel.rxQuantity changed)
        return Obx(() => Scaffold( // 1a. This Obx...
            appBar: AppBar(
              leading: IconButton(
                  onPressed: () {
                    Get.back();
                  },
                  icon: const Icon(Icons.arrow_back)),
              title: const Text('New Product Detail Screen'),
            ),
            body: controller.loadingStatus.isLoading // 1b. ...is for loadingStatus which is an RxStatus, but it caused the error to be thrown, if I put: body: Obx(() => controller.loadingStatus.isLoading : ... ), it will not throw but when loadingStatus changed it won't refresh either
                ? const CircularProgressIndicator.adaptive()
                : Container(
                    color: Colors.pink[100],
                    child: Center(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: <Widget>[
                          Text(
                              'Quantity Func: ${_cartListController.getQuantityInCart(productId: data.id)}'),
                          Text('Qty: ${_cartEntry.quantity.value}'),
                        ],
                      ),
                    ))));
      }
    class ProductDetailScreenController extends GetxController {
      late final ProductListController _productListController =
          Get.find<ProductListController>();
      late final CartListController _cartListController =
          Get.find<CartListController>();

      RxStatus loadingStatus = RxStatus.loading();
      late RxProductData productData;
      late RxCartEntryModel cartEntry;

      Future loadData(String productId) async {
        loadingStatus = RxStatus.loading();
        ProductItemModel? productExist =
            _productListController.getProductById(productId);
        if (productExist != null) {
          productData = productExist.rx;
        } else {
            loadingStatus = RxStatus.error();
            productData = RxProductItemModel();
            return;
        }

        loadingStatus = RxStatus.success();
      }
    }

So my main question (1 in the code comment) is actually 1a and 1b that causes the error, how should I place the Obx if I need further processing on the RxVariables?

My second question (2 in the code comment) is if I need my widgets to re-execute the entire build() function and fetching the data again based on an Rx changes, but that Rx is not directly rendered in any of the returned widget

CodePudding user response:

You are changing the loadingStatus wrongly, RxStatus.success() is a constructor and calling it will return a new instance of RxStatus thus replacing your Rx variable entirely. Your Obx will thus still hold the reference to the old loadingStatus (which has never, and cannot changed) thus your Obx widget will never update

Using RxStatus properly is the key. You can check out these references as I mentioned in my comment:

https://evandrmb.medium.com/make-your-code-clean-with-getx-statemixin-80c69e502cf4

https://gist.github.com/eduardoflorence/8b5a0b5139aadb4c31ddde1d28da9323

  • Related