skip to Main Content

I would like to manage TabController state in riverpod.

But error of Undefined name 'vsync' will happen

final recentWatchScreenTabStateTestProvider = StateProvider((ref) => TabController(
    length: 3, 
    vsync: vsync, // error here
));

How to fix this?

or I can’t manage TabController state in riverpod?

If use StatefullWidget, I can use TabController.

But, I want to use TabController in another Widget.

2

Answers


  1. To get vsync you have to use the mixin SingleTickerProviderStateMixin. Here is a small example:

    class MyTabbedPage extends StatefulWidget {
      const MyTabbedPage({ super.key });
    
      @override
      State<MyTabbedPage> createState() => _MyTabbedPageState();
    }
    
    class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin {
      @override
      void initState() {
        super.initState();
        final recentWatchScreenTabStateTestProvider = StateProvider((ref) => TabController(
          length: 3, 
          vsync: this,
        ));
      }
    }
    

    If you need more info check out TabController.

    Login or Signup to reply.
  2. You can do it in a slightly different way. Let each widget that needs a TabController create one based on parameters from other providers:

    /// "parameter" provider. Track wherever you need to.
    final lengthProvider = Provider<int>((ref) {
      return 3;
    });
    
    class MyTabbedPage extends ConsumerStatefulWidget {
      const MyTabbedPage({super.key});
    
      @override
      ConsumerState<MyTabbedPage> createState() => _MyTabbedPageState();
    }
    
    class _MyTabbedPageState extends ConsumerState<MyTabbedPage>
        with SingleTickerProviderStateMixin {
      late final AutoDisposeProvider<TabController> recentWatchScreenTabStateTestProvider;
    
      @override
      void initState() {
        recentWatchScreenTabStateTestProvider = Provider.autoDispose(
          (ref) => TabController(
            length: ref.watch(lengthProvider),
            vsync: this,
          ),
        );
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        final tabCtrl = ref.watch(recentWatchScreenTabStateTestProvider);
        return TabBarView(
          controller: tabCtrl,
          children: [],
        );
      }
    }
    

    That way, in another widget where you need a TabController you can again create based on the lengthProvider (and others you define).

    But, for good, in this case it is worth abandoning the use of a provider for TabController and organizing it all through the usual StatefulWidget and overridden initState and dispose methods. And to receive parameters in initState through ref.read(lengthProvider). Each widget will have its own tab controller

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search