简体   繁体   中英

Setstate not updating the UI in flutter

I am building the form based on the JSON data. I loop through the questions list and generate the Radio buttons. I am storing the values of radio button selection in formDatas list.

Radio button values are updated in formDatas but UI is not updating after the selection, I am not sure what am I missing

class Questionnaire extends StatefulWidget {
  @override
  _QuestionnaireState createState() => _QuestionnaireState();
}

class _QuestionnaireState extends State<Questionnaire> {
  final GlobalKey<FormState> formKey = GlobalKey<FormState>();
  List<Widget> fieldList = [];
  List<dynamic> questions = [
    {
      "minLabel": {"en": "default"},
      "maxValue": null,
      "type": "SWITCH",
      "weightLogics": [],
      "maxLabel": {"en": "default"},
      "enabled": false,
      "points": null,
      "minValue": null,
      "includeInScore": false,
      "intro": {"en": "default"},
      "name": "",
      "options": [
        {
          "id": "jhjhkjhk",
          "choiceFeedback": "true",
          "correct": false,
          "choiceText": {"en": "Yes"},
          "value": 0.0,
          "seq": 0.0
        },
        {
          "id": "sjgjsf",
          "choiceFeedback": "false",
          "correct": false,
          "choiceText": {"en": "No"},
          "value": 0.0,
          "seq": 1.0
        }
      ],
      "id": "0sdlfsdf",
      "text": {"en": "Are you new"}
    },
  ];
  List<Map<String, dynamic>> formDatas = [];
  void initState() {
    super.initState();
    questions.forEach((question) {
      Map<String, dynamic> data = {'questionId': question["id"], 'value': ''};
      formDatas.add(data);
    });

    fieldList = createFields();
  }


  List<Widget> createFields() {
      questions.forEach((question) {
        if (question['type'] == 'SWITCH') {
          fieldList.add(createRadioFields(question));
        }
      });
    return fieldList;
  }

  Widget createRadioFields(question) {
    final index = formDatas.indexWhere((element) => element["questionId"] == question["id"]);
    return Container(
      margin: EdgeInsets.all(15.0),
      decoration: BoxDecoration(
        border: Border(bottom: BorderSide(color: Colors.grey, width: 1))
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          new Text(
            question["text"]["en"],
            style: TextStyle(color: Colors.blue),
          ),
          Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: question['options']
                  .map<Widget>((option) => RadioListTile(
                      title: Text(option["choiceText"]["en"]),
                      value: option["choiceFeedback"],
                      groupValue: formDatas[index]["value"],
                      onChanged: (value) {
                        setState(() {
                          print(value);
                          formDatas[index]["value"] = value;
                          formDatas = formDatas;
                        });
                      }))
                  .toList())
        ],
      ),
    );
  }

  Widget createForm() {
    return Form(
        key: formKey,
        child: SingleChildScrollView(
          child: Column(children: fieldList),
        ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Questionnaire'),
        ),
        body: createForm());
  }
}

With createFields() only called in initState() , this will only ever run once, on first build. After that, it will never be called again. setState() will call the build() method again, but not initState .

So, move createFields() out of initState and into build() .

  void initState() {
    super.initState();
    questions.forEach((question) {
      Map<String, dynamic> data = {'questionId': question["id"], 'value': ''};
      formDatas.add(data);
    });

    //fieldList = createFields(); // move this into build ↓  ************
  }

The build() method of your StatefulWidget:

  @override
  Widget build(BuildContext context) {
    fieldList = createFields(); // ← re/build fields ************

    return Scaffold(
        appBar: AppBar(
          title: Text('Questionnaire'),
        ),
        body: createForm());
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM