Florian
Florian

Reputation: 266

Is there a connection between State variable and Widget variable in Flutter?

I have following problem:

I have a Stafeful Widget where I pass the parameter [Text('Test1'), Text('Test2')]:

class FirstWidget extends StatefulWidget {
  final List<Text> names;
  const FirstWidget(this.names);

  @override
  _FirstWidgetState createState() => _FirstWidgetState();
}

class _FirstWidgetState extends State<FirstWidget> {
  late List<Text> stateNames;

  @override
  void initState() {
    stateNames = widget.names;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ElevatedButton(
        child: Text('Click Me'),
        onPressed: () {
          stateNames.add(Text('This is the new Test3'));
          print('STATE: $stateNames');
          print('WIDGET: ${widget.names}');
        },
      ),
    );
  }
}

When I press the Button, a new Text Widget gets added to the List and I get following print in the console:

STATE: [Text("Test1"), Text("Test2"), Text("This is the new Test3")]
WIDGET: [Text("Test1"), Text("Test2"), Text("This is the new Test3")]

I don't understand that, because I only added the Text to the stateNames variable. Where is the connection between widget.names and stateNames?? I would expect this output:

STATE: [Text("Test1"), Text("Test2"), Text("This is the new Test3")]
WIDGET: [Text("Test1"), Text("Test2")]

How can I prevent this behaviour, that also the widget variable gets changed?

Upvotes: 2

Views: 52

Answers (1)

Kishan Dhankecha
Kishan Dhankecha

Reputation: 1015

You are giving reference to the stateNames.

By changing the contents of the stateNames the Same will happen with widget.names.

  • To prevent this from happening you have to assign a copy of widget.name to the stateNames in initState.

  • You can simply do that by spread operator like this

  @override
  void initState() {
    stateNames = [...widget.names];
    super.initState();
  }
  • You can do this:
  @override
  void initState() {
    stateNames = widget.names.toList();
    super.initState();
  }
  • Or you can do this
  @override
  void initState() {
    stateNames = List.from(widget.names);
    super.initState();
  }

Upvotes: 1

Related Questions