Home > Back-end >  setState() or markNeedsBuild() called during build in Flutter
setState() or markNeedsBuild() called during build in Flutter

Time:01-20

in my Todo App list, I'm trying to make the global state in my task list view but I'm facing some issues. I'm using StatefulWidget and StatelessWidget. In StatelessWidget Checkbox onChanged I want to toggle the Checkbox value and comes from the parent Widget but it's showing some setState() build issue Please have a look If you can.

tasks_lists.dart


import 'package:flutter/material.dart';

class TasksList extends StatefulWidget {
  const TasksList({super.key});

  @override
  State<TasksList> createState() => _TasksListState();
}

class _TasksListState extends State<TasksList> {
  bool isChecked = false;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
        'List 1',
        style: TextStyle(
          color: Colors.black,
          decoration:
              isChecked ? TextDecoration.lineThrough : TextDecoration.none,
        ),
      ),
      trailing: TaskCheckbox(
        checkBoxState: isChecked,
        toggleCheckboxState: (bool checkedBoxState) {
          setState(
            () {
              isChecked = checkedBoxState;
            },
          );
        },
      ),
    );
  }
}

class TaskCheckbox extends StatelessWidget {
  final bool checkBoxState;
  final Function? toggleCheckboxState;

  const TaskCheckbox({
    super.key,
    required this.checkBoxState,
    this.toggleCheckboxState,
  });

  @override
  Widget build(BuildContext context) {
    return Checkbox(
      value: checkBoxState,
      onChanged: toggleCheckboxState!(checkBoxState),
      activeColor: Colors.lightBlueAccent,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(2.0),
      ),
      side: MaterialStateBorderSide.resolveWith(
        (states) => BorderSide(
          width: 2.0,
          color: Colors.black,
        ),
      ),
    );
  }
}

CodePudding user response:

This means that the function is called during build,

onChanged: toggleCheckboxState!(checkBoxState),

while this calls the function when Checkbox is tapped.

onChanged: (checkBoxState) => toggleCheckboxState!(checkBoxState),

Take a look of Introduction to widgets.

CodePudding user response:

Your toggleCheckboxState function call during building the UI, so you need to put it inside addPostFrameCallback so it run after UI builds, like this:

toggleCheckboxState: (bool checkedBoxState) {

   WidgetsBinding.instance.addPostFrameCallback((_) {
       setState(
         () {
           isChecked = checkedBoxState;
         },
       );  
   });
          
},

CodePudding user response:

You are changing value/state so you have to make TaskCheckbox a Stateful widget.

CodePudding user response:

onChange is a Fuction(bool). try to change TaskCheckbox to this:

class TaskCheckbox extends StatelessWidget {
 final bool checkBoxState;
  final Function(bool)? toggleCheckboxState;

  const TaskCheckbox({
    super.key,
    required this.checkBoxState,
    this.toggleCheckboxState,
  });
  @override
  Widget build(BuildContext context) {
    return Checkbox(
      value: checkBoxState,
      onChanged: toggleCheckboxState!,
      activeColor: Colors.lightBlueAccent,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(2.0),
      ),
      side: MaterialStateBorderSide.resolveWith(
            (states) => BorderSide(
          width: 2.0,
          color: Colors.black,
        ),
      ),
    );
  }
}
  • Related