Home > database >  Stateful widget class variable's value changed while accessing again using widget object
Stateful widget class variable's value changed while accessing again using widget object

Time:08-22

I have experience a weird behaviour in Flutter Stateful widget. I am initializing a local list from the class's final list variable using widget.variable_name. I have incorporated a function to delete an item from the local list but it affects the class variable too. How is this even possible?

Here is the code:


import 'package:flutter/material.dart';

class Test extends StatefulWidget {
  const Test({
    required this.fruits
});

  final List<String> fruits;

  static const String routeName = '/test';

  static Route route({required List<String> fruits}){
    return MaterialPageRoute(
      settings: RouteSettings(name: routeName),
      builder: (_) => Test(fruits: fruits,)


    );
  }

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {

  List<String>? _fruits;

  void deleteFruit(name){
    setState((){
      _fruits!.remove(name);
      print("_fruits: ${widget.fruits}");
      print("widget.fruits: ${widget.fruits}");
    });
  }

  @override
  void initState() {
    super.initState();
    setState(() {
     _fruits = widget.fruits;
     print("Initial fruits: $_fruits");
    });

  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Column(
          children:
          (_fruits != null) ?
          _fruits!.map((e) => ListTile(
            leading: IconButton(
             icon: Icon(Icons.remove),
                onPressed: (){
                    deleteFruit(e);
              }),
            title: Text(e),
            ),
          ).toList() : []



        ),
      ),
    );
  }
}

I am routing to this stateful widget from another widget using

Navigator.pushNamed(context, '/test',arguments: ["apple","mango","orange"]);

When I delete an item say "mango" from the list, the output is as follows,

_fruits : ["apple","orange"]
widget.fruits : ["apple","orange"] \\I was expecting to get ["apple","mango","orange"]

CodePudding user response:

I suspect the instance of object is passed by reference in your case. Try creating new list like

_fruits = widget.fruits.toList();

Also while feeding on constructor, you can DO

Test(fruits: yourItems.toList(),

You can check Is Dart pass by reference

CodePudding user response:

One should see that Dart it isn't a language that copy the value of variables. So when you pass the fruits down the state, you'll be sending the reference of that list, and that reference points out to the original object. To solve this, you need to copy the list before remove, and assign the new copy to the _fruits variable at the state.

class _TestState extends State<Test> {

  List<String>? _fruits;

  ...

  @override
  void initState() {
    super.initState();
    setState(() {
     _fruits = [...widget.fruits]; // Copies the objects reference to a new List
     print("Initial fruits: $_fruits");
    });

  }
 ...
  • Related