Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter setState to another class?

I have a root class RootPage which is a StatefulWidget which is always in view. I would like to change the body in RootPage which is controlled by RootPage's currentPage Widget from different classes such as my FeedPage class and any other class that I make?

Example code

import 'package:flutter/material.dart';

class RootPage extends StatefulWidget {
  @override
  _RootPageState createState() => new _RootPageState();
}
class _RootPageState extends State<RootPage> {
  FeedPage feedPage;

  Widget currentPage;

  @override
  void initState() {
    super.initState();
    feedPage = FeedPage();

    currentPage = feedPage;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      //Current page to be changed from other classes too?
      body: currentPage
    );
  }
}



class FeedPage extends StatefulWidget {
  @override
  _feedPageState createState() => new _feedPageState();
}
class _feedPageState extends State<FeedPage> {

  @override
  Widget build(BuildContext context) {
    return new FlatButton(
      onPressed: () {
        setState(() {
          //change the currentPage in RootPage so it switches FeedPage away and gets a new class that I'll make
        });
      },
      child: new Text('Go to a new page but keep root, just replace this feed part'),
    );
  }
}

I'm sure there's an obvious answer but I can't seem to figure out how to do it efficiently so it'll be easy to integrate future classes and keep my Root always in view.

like image 652
Jayden Avatar asked Aug 11 '18 09:08

Jayden


People also ask

How do you use setState in a class in Flutter?

When you change the state of a Stateful Widget, use setState() to cause a rebuild of the widget and its descendants. You don't need to call setState() in the constructor or initState() of the widget, because build() will be run afterward anyway. Also don't call setState() in synchronous code inside build().

What is the alternative of setState in Flutter?

ValueNotifier requires a bit more code than setState .


3 Answers

You can use callbacks functions to achieve this. Please refer to the below code.

import 'package:flutter/material.dart';

class RootPage extends StatefulWidget {
  @override
  _RootPageState createState() => new _RootPageState();
}
class _RootPageState extends State<RootPage> {
  FeedPage feedPage;

  Widget currentPage;

  @override
  void initState() {
    super.initState();
    feedPage = FeedPage(this.callback);

    currentPage = feedPage;
  }

  void callback(Widget nextPage) {
    setState(() {
      this.currentPage = nextPage;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      //Current page to be changed from other classes too?
        body: currentPage
    );
  }
}



class FeedPage extends StatefulWidget {
  Function callback;

  FeedPage(this.callback);

  @override
  _feedPageState createState() => new _feedPageState();
}
class _feedPageState extends State<FeedPage> {

  @override
  Widget build(BuildContext context) {
    return new FlatButton(
      onPressed: () {
        this.widget.callback(new NextPage());
//        setState(() {
//          //change the currentPage in RootPage so it switches FeedPage away and gets a new class that I'll make
//        });
      },
      child: new Text('Go to a new page but keep root, just replace this feed part'),
    );
  }
}

This is very similar to this problem and you could refer 3rd point in my answer.

like image 189
Dinesh Balasubramanian Avatar answered Oct 22 '22 16:10

Dinesh Balasubramanian


Screenshot (Null safe):

enter image description here


Full code:

This is the ParentPage:

class ParentPage extends StatefulWidget {
  @override
  _ParentPageState createState() => _ParentPageState();
}

class _ParentPageState extends State<ParentPage> {
  int _count = 0;

  // Pass this method to the child page.
  void _update(int count) {
    setState(() => _count = count);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Text('Value (in parent) = $_count'),
          ChildPage(update: _update),
        ],
      ),
    );
  }
}

This is the ChildPage:

class ChildPage extends StatelessWidget {
  final ValueChanged<int> update;
  ChildPage({required this.update});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () => update(100), // Passing value to the parent widget.
      child: Text('Update (in child)'),
    );
  }
}
like image 31
CopsOnRoad Avatar answered Oct 22 '22 15:10

CopsOnRoad


I know that you need a solution for your specific code but I recommed to you to have a look on BloC pattern as it the recommended aproch when you want to pass state changes from widget to another especially multiple pages

the idea is simple although the implementation is a "little bit" more complicated

like image 2
Saed Nabil Avatar answered Oct 22 '22 15:10

Saed Nabil