Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to avoid 'FlutterError (setState() or markNeedsBuild() called during build.' #149

Closed
2shrestha22 opened this issue Nov 17, 2020 · 15 comments

Comments

@2shrestha22
Copy link

Using Injected Model I am trying to fetch articles from end point. I am using TabBar to switch between different category.

  body: TabBarView(
          children: [
            ArticleListView(),
            ArticleListView(),
          ],
        ),

Inside ArticleListView() I am using wpPageServiceIM.whenRebuilderOr(). While switching from tabbar (tabbar with same page) it gives exception saying 'FlutterError (setState() or markNeedsBuild() called during build.'
How should I overcome this? I have single service to fetch article from end point final wpPageServiceIM = RM.inject<WpPageService>(() => WpPageService(api: _api.state));
While suing StateBuilder() solves the issue.

I am new at programming, if my question is silly sorry for that.

@GIfatahTH
Copy link
Owner

Hi @2shrestha22 . Thank you for opening this issue.

Does this example represent your case? It works for me, try it and see if it works for you too.

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

class _App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: DefaultTabController(
          length: 3,
          child: Scaffold(
            appBar: AppBar(
              bottom: TabBar(
                tabs: [
                  Tab(icon: Icon(Icons.directions_car)),
                  Tab(icon: Icon(Icons.directions_transit)),
                  Tab(icon: Icon(Icons.directions_bike)),
                ],
              ),
            ),
            body: TabBarView(
              children: [
                ArticleListView(),
                ArticleListView(),
                ArticleListView(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class ArticleListView extends StatelessWidget {
  final wpPageServiceIM = RM.injectFuture(
    () => Future.delayed(Duration(seconds: 1), () => 1),
  );

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        wpPageServiceIM.whenRebuilderOr(
          onWaiting: () => CircularProgressIndicator(),
          onError: null,
          builder: () => Text('${wpPageServiceIM.state}'),
        ),
      ],
    );
  }
}

@2shrestha22
Copy link
Author

2shrestha22 commented Nov 17, 2020

Moving final wpPageServiceIM = RM.inject<WpPageService>(() => WpPageService(api: _api.state)); inside ArticleListView worked. So the problem comes when I make the model global (inside injected.dart).

@duniapay
Copy link

Hi @GIfatahTH How to make the injected model available to other widgets using the example you provided above ?

@duniapay
Copy link

I am facing the same issue using global injection. Here is my code below.

registrationViewStore.setState(
                  (s) {
                    return s.onContinueTapped();
                  },
                  catchError: true,
                  onError: (context, error) {
                    log(error.toString());
                  },
                );

@amoslai5128
Copy link
Collaborator

I am facing the same issue using global injection. Here is my code below.

registrationViewStore.setState(
                  (s) {
                    return s.onContinueTapped();
                  },
                  catchError: true,
                  onError: (context, error) {
                    log(error.toString());
                  },
                );

Can you provide some more details?

@duniapay
Copy link

duniapay commented Nov 28, 2020

I have a Screen with 5 PageViews inside. Each one of the pageview is controlled by a button in the MainScreen Page.

My custom button in the main screen

registrationViewStore.whenRebuilderOr(
                    onWaiting: () => ButtonLoaderIndicatorWidget(),
                    builder: () => CustomButton(
                          color: Constants().primaryColor,
                          buttonText: btnText,
                          onPressed: () {
                            log('should log');
                            registrationViewStore
                              .setState(
                                (s) => s.onContinueTapped(),
                                catchError: true,
                                onError: (context, error) {
                                  log(error.toString());
                                },
                              );
                          },
                        ))

When I perform a set state from the onPressed I am getting this error

FlutterError (setState() or markNeedsBuild() called during build

@duniapay
Copy link

The issue only happens when I use setState. Since I am using PageViews I kinda need to set the state. I am not finding any solution to this problem since 3 days. Can you please assist ? @amoslai5128

@amoslai5128
Copy link
Collaborator

The issue only happens when I use setState. Since I am using PageViews I kinda need to set the state. I am not finding any solution to this problem since 3 days. Can you please assist ? @amoslai5128

Where do you define the "registrationViewStore"? Is its data type a PageController?

@duniapay
Copy link

registrationViewStore is define as a global injectable like this

final registrationViewStore = RM.inject(
  () => RegistrationState.initial(authenticationRepository.state),
);

@amoslai5128
Copy link
Collaborator

registrationViewStore is define as a global injectable like this

final registrationViewStore = RM.inject(
  () => RegistrationState.initial(authenticationRepository.state),
);

Can you share the code of your CustomButton? It seems like it might be related to the onPress

@duniapay
Copy link

sure here is the custom button below @amoslai5128

import 'package:flutter/material.dart';

enum ButtonState { Busy, Idle }

class CustomButton extends StatefulWidget {
  final String buttonText;
  final Function onPressed;
  final Color color;

  CustomButton(
      {@required this.buttonText,
      @required this.onPressed,
      @required this.color});
  @override
  _CustomButtonState createState() => _CustomButtonState();
}

class _CustomButtonState extends State<CustomButton> {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      top: false,
      child: Container(
        height: 54,
        width: double.infinity,
        decoration: BoxDecoration(
          color: widget.color,
          borderRadius: BorderRadius.circular(30),
          boxShadow: [
            BoxShadow(
              color: Color.fromRGBO(38, 59, 186, 0.2),
              spreadRadius: 2,
              blurRadius: 6,
              offset: Offset(0, 3), // changes position of shadow
            ),
          ],
        ),
        margin: EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10),
        child: FlatButton(
          onPressed: widget.onPressed,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(40),
          ),
          color: widget.color,
          disabledColor: Color(0xff4458C1),
          child: Text(
            widget.buttonText,
            style: TextStyle(
              color: Colors.white,
              letterSpacing: 0.5,
              fontWeight: FontWeight.bold,
              fontSize: 16, //MediaQuery.of(context).size.height * 0.02,
            ),
          ),
        ),
      ),
    );
  }
}

@duniapay
Copy link

duniapay commented Nov 29, 2020

I have updated the custom to be a statelessWidget instead. I am still getting the same error

Unhandled Exception: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4263 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
E/flutter (12573): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
E/flutter (12573): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
E/flutter (12573): #2      Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4263
E/flutter (12573): #3      State.setState
package:flutter/…/widgets/framework.dart:1264
E/flutter (12573): #4      StateBuilderState.update
package:states_rebuilder/…/builders/state_builder.dart:305
E/flutter (12573): #5      StatesRebuilder.rebuildStates
package:states_rebuilder/src/states_rebuilder.dart:170
E/flutter (12573): #6      _SetState.rebuildStates
package:states_rebuilder/…/reactive_model/set_state.dart:113
E/flutter (12573): #7      _SetState.onErrorCallBack
package:states_rebuilder/…/reactive_model/set_state.dart:158
E/flutter (12573): #8      _SetState._futureHandler.<anonymous closure>
package:states_rebuilder/…/reactive_model/set_state.dart:

@amoslai5128
Copy link
Collaborator

amoslai5128 commented Nov 30, 2020

Function onPressed;

Can you try to replace your final Function onPressed; to final VoidCallback onPressed;?

@amoslai5128
Copy link
Collaborator

I have updated the custom to be a statelessWidget instead. I am still getting the same error

Unhandled Exception: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4263 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
E/flutter (12573): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
E/flutter (12573): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
E/flutter (12573): #2      Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4263
E/flutter (12573): #3      State.setState
package:flutter/…/widgets/framework.dart:1264
E/flutter (12573): #4      StateBuilderState.update
package:states_rebuilder/…/builders/state_builder.dart:305
E/flutter (12573): #5      StatesRebuilder.rebuildStates
package:states_rebuilder/src/states_rebuilder.dart:170
E/flutter (12573): #6      _SetState.rebuildStates
package:states_rebuilder/…/reactive_model/set_state.dart:113
E/flutter (12573): #7      _SetState.onErrorCallBack
package:states_rebuilder/…/reactive_model/set_state.dart:158
E/flutter (12573): #8      _SetState._futureHandler.<anonymous closure>
package:states_rebuilder/…/reactive_model/set_state.dart:

Have you solved the problem?

@amoslai5128
Copy link
Collaborator

I have updated the custom to be a statelessWidget instead. I am still getting the same error

Unhandled Exception: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4263 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
E/flutter (12573): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
E/flutter (12573): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
E/flutter (12573): #2      Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4263
E/flutter (12573): #3      State.setState
package:flutter/…/widgets/framework.dart:1264
E/flutter (12573): #4      StateBuilderState.update
package:states_rebuilder/…/builders/state_builder.dart:305
E/flutter (12573): #5      StatesRebuilder.rebuildStates
package:states_rebuilder/src/states_rebuilder.dart:170
E/flutter (12573): #6      _SetState.rebuildStates
package:states_rebuilder/…/reactive_model/set_state.dart:113
E/flutter (12573): #7      _SetState.onErrorCallBack
package:states_rebuilder/…/reactive_model/set_state.dart:158
E/flutter (12573): #8      _SetState._futureHandler.<anonymous closure>
package:states_rebuilder/…/reactive_model/set_state.dart:

@duniapay
Just turn off the All Exceptions from your vscode
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants