33

When I want to do "Extract to widget", it raises an error : "reference to an enclosing class method cannot be extracted"

I know there is some variables that must get their data from class constructor but I want Android studio to extract the widget then, I will correct the mistaken codes, like Visual Studio that without any error extract the code to a new widget then it needs to copy the new extracted widget to a new dart file and correct the mistakes.

I want to extract the Card widget part.

import 'package:flutter/material.dart';
import 'package:flutter/material.dart' as prefix0;
import 'package:intl/intl.dart';
import '../model/transaction.dart';

class TransactionList extends StatelessWidget {
  final List<Transaction> transactions;
  final Function deleteTx;

  TransactionList(this.transactions, this.deleteTx);

  @override
  Widget build(BuildContext context) {
    return transactions.isEmpty
        ? LayoutBuilder(
            builder: (ctx, constraint) {
              return Column(
                children: <Widget>[
                  Text(
                    'There is no transaction',
                    style: Theme.of(context).textTheme.title,
                    textDirection: prefix0.TextDirection.rtl,
                  ),
                  SizedBox(
                    height: 10,
                  ),
                  Container(
                      height: constraint.maxHeight * 0.6,
                      child: Image.asset(
                        'assets/images/yalda.png',
                        fit: BoxFit.cover,
                      ))
                ],
              );
            },
          )
        : ListView.builder(
            itemCount: transactions.length,
            itemBuilder: (ctx, index) {
              return **Card**(
                margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 5),
                elevation: 5,
                child: ListTile(
                  leading: CircleAvatar(
                    radius: 30,
                    child: Padding(
                      padding: const EdgeInsets.all(8),
                      child: FittedBox(
                          child: Text('\$${transactions[index].amount}')),
                    ),
                  ),
                  title: Text(
                    transactions[index].title,
                    style: Theme.of(context).textTheme.title,
                  ),
                  subtitle: Text(DateFormat.yMMMd()
                      .format(transactions[index].date)
                      .toString()),
                  trailing: MediaQuery.of(context).size.width > 360
                      ? FlatButton.icon(
                          onPressed: () => deleteTx(transactions[index].id),
                          icon: const Icon(Icons.delete),
                          label: const Text('Delete'),
                    textColor: Theme.of(context).errorColor,
                  )
                      : IconButton(
                          icon: const Icon(Icons.delete),
                          color: Theme.of(context).errorColor,
                          onPressed: () => deleteTx(transactions[index].id),
                        ),
                ),
              );
            });
  }
}
Behzad
  • 1,740
  • 1
  • 22
  • 49

13 Answers13

30

Simply use "Extract Method" instead of "Extract Widget". VSCode will add all the returns and references.

Edit: If you want to use "Extract Widget" only then simply wrap that widget in a Container and then use "Extract Widget" on that widget. If that doesn't work, comment out setState() function inside the widget and try again.

Toshik Langade
  • 758
  • 7
  • 13
  • 3
    we can use Extract method or we manually extract the widget, but is there any convention when to use extract method or extract widget? sorry I am new in Flutter :) – sarah Feb 20 '21 at 23:17
9

Your deleteTx might contain a setState(() {}) method, try to comment that part of your code where you're calling deleteTx it and just put it back after your extraction.

MykeCAMARA
  • 109
  • 1
  • 3
5

Just remove or comment the setState() {} from your widget and it gonna works.

nextloop
  • 166
  • 9
Ayz
  • 181
  • 1
  • 9
3

transform onpressed etc. property to comments and then try again 'Extract Widget' and go on

Eray Hamurlu
  • 657
  • 7
  • 9
2

I had the same issue and in my case it was because of ListView.builder as yours.

So it is easy to fix, Simply make a class and return Card in Widget build and return it in ListView.builder inside the TransactionList class with the desired arguments.

Nazanin Nasab
  • 595
  • 8
  • 18
2

If you can comment out deleteTx(transactions[index].id) parts of your code and then use onPressed: (){}, you will be able to extract to widget.

After the extraction you can use:

onPressed: (){
    setState(() {
        deleteTx(transactions[index].id);
    });
}
sleep
  • 4,855
  • 5
  • 34
  • 51
Aaydin
  • 192
  • 1
  • 6
2

You have to care about a few things:

  1. Whenever you are extracting a widget, that widget should not contain any variable which is used in the current working page.
  2. All the functions or methods should be parametric.
SeReGa
  • 1,219
  • 2
  • 11
  • 32
1

It is because you are referencing a variable(for example, transactions) in your Card widget from the enclosing class i.e. TransactionList. The best way to extract in this case could be to just make stateless/stateful widget outside your class and cut the Card widget and paste it as the return type of the build method of that Widget you created. And you can reference those variables using the constructor of that widget you created.

NullByte08
  • 884
  • 10
  • 15
0

there might be some local referance to the variable in the current class,so if there some referance we cant extract a widget from there.

Akhil
  • 419
  • 5
  • 15
0

You can use the "Extract Method". It's a simple way. VSCode will add all the returns and references.

0

If we extract the widget it will StatelessWidget. StatelessWidget doesn't support changing state so if you use any Onchange property SetState it never extract so please remove setState(() {});

Musfiq Shanta
  • 1,298
  • 13
  • 9
0

Just remove or comment the setState() {} from your widget

Or

Just remove or comment the MediaQuery.of(context).size.width from your widget

Anand
  • 4,355
  • 2
  • 35
  • 45
0

There are multiple reasons for this warning.

  1. If you are using setState inside the block which you are trying to extract. The solution for this is to try commenting on the setState block.
  2. If you are using any properties or functions related to the existing class then also we can see this warning. Solution for this is to either try by making the properties or function globally accessible (if possible) or try to pass the only the value to the widget as arguments.
Akhil
  • 419
  • 5
  • 15