Eustace
Eustace

Reputation: 37

How do access a class variable in stateful widget in flutter?

I am passing the total variable from another widget then using it in the class loan.

    class Loan extends StatefulWidget {
      final int total;
    
      Loan(this.total);
      int get t {
        return total;
      }
    
    class _LoanState extends State<Loan> {
      var loanEligible = applyLoan(widget.total);
    //method apply loan
    Map applyLoan(int total) {
        var constraints = {};
    
        if (widget.total <= 500) {
          constraints = {"from": 3000, "to": 15000};
        } else if (widget.total <= 200) {
          constraints = {"from": 1000, "to": 5000};
        } else {
          constraints = null;
        }
        return constraints;
      }

When trying to assign a value to the loanEligible variable I am gettinng this error: The instance member 'widget' can't be accessed in an initializer.

Upvotes: 3

Views: 6765

Answers (2)

Owczar
Owczar

Reputation: 2593

You forgot about createState method in Loan and build method in _LoanState.

About your problem: you can use initState method. More about State class you can read in the documentation

class Loan extends StatefulWidget {
  final int total;

  const Loan(this.total, { Key key }) : super(key: key);
  
  @override
  _LoanState createState() => _LoanState();
}

class _LoanState extends State<Loan> {
  int loanEligible;
  
    @override
  Widget build(BuildContext context) {
    return Container(color: const Color(0xFFFFE306));
  }

  @override
  void initState() {
    super.initState();
    loanEligible = applyLoan(widget.total);
  }
  
  //method apply loan
   Map applyLoan(int total) {
    var constraints = {};

    if (total <= 500) {
      constraints = {"from": 3000, "to": 15000};
    } else if (total <= 200) {
      constraints = {"from": 1000, "to": 5000};
    } else {
      constraints = null;
    }
    return constraints;
  }
}

Are you sure you need to use StatefulWidget? Have you considered StatelessWidget? Stateless widget is for widgets that always build the same way given a particular configuration and ambient state. It means if you don't rebuild your widget during its lifecycle, if widget can't change, you can use StatelessWidget. Good examples of StatelessWidgets in Flutter are Text or Icon. If you don't know, which type of widgets you do need, you can write StatefulWidget and at the end check if you used setState() method - if not, you can transform your widget into StatelessWidget.

About StatefulWidget: https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

About StatelesWidget: https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html

Your class as StatelessWiget and overwrite createElement metohd:

class Loan extends StatelessWidget {
  final int total;

  const Loan(this.total, { Key key }) : super(key: key);
  
    @override
  Widget build(BuildContext context) {
    return Container(color: const Color(0xFFFFE306));
  }
  
  @override
  void createElement() {
    super.createElement();
    loanEligible = applyLoan(total);
  }
    
  //method apply loan
  Map applyLoan(int total) {
    var constraints = {};

    if (total <= 500) {
      constraints = {"from": 3000, "to": 15000};
    } else if (total <= 200) {
      constraints = {"from": 1000, "to": 5000};
    } else {
      constraints = null;
    }
    return constraints;
  }
}

Moreover, if you don't want to build a widget, but only create a class to calculate something, you can create non-widget class:

class Loan {
  final int total;

  const Loan(this.total);
  
    
  //method apply loan
  Map applyLoan(int total) {
    var constraints = {};

    if (total <= 500) {
      constraints = {"from": 3000, "to": 15000};
    } else if (total <= 200) {
      constraints = {"from": 1000, "to": 5000};
    } else {
      constraints = null;
    }
    return constraints;
  }
}

Upvotes: 3

Alex Radzishevsky
Alex Radzishevsky

Reputation: 3768

You are trying to initialize state value with initializer. At the moment of State object initialization there is still no access to its fields (including widget field, as object is not constructed yet).

What you can do though is use initState lifecycle method of State to initialize loanEligible map:

class _LoanState extends State<Loan> {
  Map loanEligible;
  
  @override
  void initState() {
    super.initState();
    
    loanEligible = applyLoan(widget.total);
  }
 //...
}

Upvotes: 4

Related Questions