0

I am making a login page with a inkwell that navigate to forget password page. without adding the code of navigation, It works well. Once I put the navigation code, an error appear " setState() or markNeedsBuild() called during build." and then the next page appear without tapping the button.

this is the start of Login page:

class LoginPage extends StatefulWidget {
 @override
 _LoginPageState createState() => _LoginPageState();
 }

class _LoginPageState extends State<LoginPage> {
 final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

String email = "", password = "", passwordErrorText, emailErrorText;
 FocusNode emailFocus, passwordFocus;

 @override
void initState() {
super.initState();

emailFocus = FocusNode();
passwordFocus = FocusNode();
passwordErrorText = null;
emailErrorText = null;
emailFocus.addListener(() {
  if (!emailFocus.hasFocus) {
    if (!TextFieldValidator().emailValidator.isValid(email.toLowerCase())) {
      setState(() {
        emailErrorText = TextFieldValidator().emailValidator.errorText;
      });
    } else {
      setState(() {
        emailErrorText = null;
      });
    }
  }
   });
 }

and this is the button:

         Padding(
            padding: EdgeInsets.only(top: 20),
            child: InkWell(
              child: Text(
                forgetPassText,
                style: TextStyle(color: Colors.blue),
              ),
              onTap: Router.goToForgetPassword(context),
            ))
      ])),

and this is the function that navigate

static goToForgetPassword(BuildContext context) {
Navigator.push(
    context,
    PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) =>
          ForgetPasswordPage(),
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return child;
      },
    ));

}

Liza
  • 23
  • 8
  • you are not closing the initState{} function and you are doing everything inside the initialization (building) of the app and thats not the right way: @override void initState() { super.initState(); – Ridha Rezzag Aug 10 '20 at 22:28

2 Answers2

2

The problem is very simple: you are calling the function, you should be giving a function that calls the function. So this line should become:

              onTap: () => Router.goToForgetPassword(context),

Earlier, you were calling goToForgetPassword and giving to onTap whatever it returns (probably null). But now we are creating a function to be called in the future, and giving that function to be called to onTap.

If you can put a breakpoint inside goToForgetPassword function and debug, you will also see this for yourself.

Gazihan Alankus
  • 11,256
  • 7
  • 46
  • 57
1

Replace

 Padding(
            padding: EdgeInsets.only(top: 20),
            child: InkWell(
              child: Text(
                forgetPassText,
                style: TextStyle(color: Colors.blue),
              ),
              onTap: Router.goToForgetPassword(context),
            ))
      ])),

by

 Padding(
            padding: EdgeInsets.only(top: 20),
            child: InkWell(
              child: Text(
                forgetPassText,
                style: TextStyle(color: Colors.blue),
              ),
              onTap: () => Router.goToForgetPassword(context),
            ))
      ])),

In this case the InkWell will wait for the click , not launching the function while rendering.

ikerfah
  • 2,612
  • 1
  • 11
  • 18