Home > Mobile >  Using setState in void function and get a warning that the void function(dynamic) cannot be assigned
Using setState in void function and get a warning that the void function(dynamic) cannot be assigned

Time:05-21

I'm getting a warning that The argument type 'void Function(dynamic)' can't be assigned to the parameter type 'void Function()' which is line right below the String dialogText. I used this function to pass data from Child widget, TopAppBar, to Parent widget which is MyApp. From the child widget, TopAppBar, I used TextFormField to type the word to change the text when it's submitted.

I saw the other codes that have no problem, so I don't know how to solve this problem.

Please help me! Thank you!

class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int count = 0;
  var nameList = ['one','two','three','four'];
  String dialogText = "Hello!";

  void _changeDialogText(value){
    setState((value){
      dialogText = value;
    });
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
            appBar: TopAppBar(state: _changeDialogText,),
            body: Column(
              children: [
                Container(
                  height: 400,
                  child: (
                    ListView(
    children: List.generate(
        nameList.length, (index) => CustomListTile(title: nameList[index])),
                    )
                  )
                ),
                Container(
                  height: 20, child: Text(count.toString())
                ),
                Container(
                    height: 20, child: Text(dialogText)
                ),
              ],
            ),
          floatingActionButton: FloatingActionButton(
            child: Text('Button'),
            onPressed: (){
              print('a');
              setState(
                  (){
                    count  ;
                  }
              );
            },
          ),
          bottomNavigationBar: BottomBar(),
            floatingActionButtonLocation: FloatingActionButtonLocation.endDocked
        );

  }
}
class TopAppBar extends StatefulWidget  with PreferredSizeWidget{
  const TopAppBar({Key? key, required this.state(value)}) : super(key: key);
  final Function(String value) state;

  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight);
  State<TopAppBar> createState() => _TopAppBarState();
}


class _TopAppBarState extends State<TopAppBar> {
  final TopAppBarData _topAppBarData = TopAppBarData();
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  @override

  Widget build(BuildContext context) {
    return Form(
      child:
        AppBar(
            flexibleSpace: Container(
              decoration: BoxDecoration(
                  gradient: LinearGradient(
                      begin: Alignment.centerLeft,
                      end: Alignment.centerRight,
                      colors: <Color>[Color.fromRGBO(180, 44, 77, 1) , Color.fromRGBO(242, 114, 59, 1)]
                  )
              ),
            ),
          elevation: 0.0,
          centerTitle: false,
          title: Row(
            children: [
              Text(
                'SSG',
                style: TextStyle(
                  color: Colors.white,
                ),
              ),
              Icon(
                Icons.expand_more,
                color: Colors.black,
              )
            ],
          ),
          actions: [
            Padding(
                padding: EdgeInsets.only(right: 30.0),
                child: IconButton(
                  icon: Icon(Icons.search),
                    color: Colors.black,
                  onPressed: (){
                    showDialog(context: context, builder: (context){
                      return AlertDialog(
                        title: Text('Search'),
                        content: TextFormField(
                          onChanged: (value) {
                            widget.state(value);
                          },
                          decoration: InputDecoration(hintText: "Text Field in Dialog"),
                        ),
                        actions: <Widget>[
                          ElevatedButton(
                            child: Text('CANCEL'),
                            onPressed: () {
                              setState(() {
                                Navigator.pop(context);
                              });
                            },
                          ),
                          ElevatedButton(
                            child: Text('OK'),
                            onPressed: () {
                              setState(() {
                                Navigator.pop(context);
                              });
                            },
                          ),
                        ],
                      );
                    });
                  },
                )
            ),
            Padding(
                padding: EdgeInsets.only(right: 30.0),
                child: GestureDetector(
                  onTap: () {},
                  child: Icon(
                    Icons.menu,
                    color: Colors.black,
                  ),
                )
            ),
            Padding(
                padding: EdgeInsets.only(right: 30.0),
                child: GestureDetector(
                  onTap: () {},
                  child: Icon(
                    Icons.notification_add,
                    color: Colors.black,
                  ),
                )
            ),
          ],
        ),
    );
  }
}

CodePudding user response:

the setState() function doesn't pass any arguments to the callback. The code should look like this:

setState(() {
    dialogText = value;
});

CodePudding user response:

change this

void _changeDialogText(value){
    setState((value){
      dialogText = value;
    });
  }

to

void _changeDialogText(String value){
        setState((value){
          dialogText = value;
        });
      }

CodePudding user response:

If you omit types, dynamic is assumed by the compiler. Don't do that. Turn on your linter (it should be on by default) and it will warn you about it.

final /* --> */ void /* <-- */  Function(String value) state;

and

void _changeDialogText( /* --> */ String /* <-- */ value){

Now, the signatures match.

CodePudding user response:

Your problem stems from how you're setting your state. The setState function takes an argument of void Function() as seen below:

package:flutter/src/widgets/framework.dart 
void setState(void Function() fn)  
Containing class: State  Type: void Function(void Function())

However, you add an unnecessary argument value of type dynamic. Changing

 void _changeDialogText(value){
     setState((value){
         dialogText = value;
     });
 }

to

 void _changeDialogText(String value){
     setState((){
         dialogText = value;
    });
 }

will get rid of that warning. But you may want to consider using explicit types and force that by adding implicit-dynamic to your analysis options file.

Also, when initializing your final Function(String value) state; variable in the constructor, you use:

const TopAppBar({Key? key, required this.state(value)}) : super(key: key);

However, this is unnecessary and is missing a type on the "value" parameter. so you may use this instead:

const TopAppBar({Key? key, required this.state}) : super(key: key);
  • Related