<aside> 💡 바텀 네비게이션이나 탭바를 만들었을때 탭을 하나하나 누를대마다 탭바가 변경되는 그 스크린들이 각각의 라우트로 지정되게 하고 싶은 경우가 분명히 있고 직관적이다

</aside>

그럴때 쓰는 것이 Shell Route

ShellRoute(
          builder: (context, state, child) {
            return NestedScreen(child: child);
          },
          routes: [
            // /nested/a
            GoRoute(
              path: 'nested/a',
              builder: (_, state) => NestedChildScreen(
                routeName: '/nested/a',
              ),
            ),
            // /nested/b
            GoRoute(
              path: 'nested/b',
              builder: (_, state) => NestedChildScreen(
                routeName: '/nested/b',
              ),
            ),
            // /nested/c
            GoRoute(
              path: 'nested/c',
              builder: (_, state) => NestedChildScreen(
                routeName: '/nested/c',
              ),
            ),
          ],
        ),

ShellRoute 안에 child에 들어가는 값들을 우리가 route안의 goRoute를 선언해 입력해 주어야한다.

GoRoute에는 path가 있지만 ShellRoute에는 path가 없기때문애

순서대로 /nested/a, /nested/b, /nested/c로 해석이 된다.

사용예시

nested_child.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

class NestedScreen extends StatelessWidget {
  final Widget child;

  const NestedScreen({
    required this.child,
    Key? key,
  }) : super(key: key);

  int getIndex(BuildContext context){
    if(GoRouterState.of(context).location == '/nested/a'){
      return 0;
    }else if(GoRouterState.of(context).location == '/nested/b'){
      return 1;
    }else{
      return 2;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('${GoRouterState.of(context).location}'),
      ),
      body: child,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: getIndex(context),
        onTap: (index){
          if(index == 0){
            context.go('/nested/a');
          }else if(index == 1){
            context.go('/nested/b');
          }else {
            context.go('/nested/c');
          }
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(
              Icons.home,
            ),
            label: 'home',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.person,
            ),
            label: 'person',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.notifications,
            ),
            label: 'notifications',
          ),
        ],
      ),
    );
  }
}

nested_screen.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

class NestedScreen extends StatelessWidget {
  final Widget child;

  const NestedScreen({
    required this.child,
    Key? key,
  }) : super(key: key);

  int getIndex(BuildContext context){
    if(GoRouterState.of(context).location == '/nested/a'){
      return 0;
    }else if(GoRouterState.of(context).location == '/nested/b'){
      return 1;
    }else{
      return 2;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('${GoRouterState.of(context).location}'),
      ),
      body: child,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: getIndex(context),
        onTap: (index){
          if(index == 0){
            context.go('/nested/a');
          }else if(index == 1){
            context.go('/nested/b');
          }else {
            context.go('/nested/c');
          }
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(
              Icons.home,
            ),
            label: 'home',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.person,
            ),
            label: 'person',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.notifications,
            ),
            label: 'notifications',
          ),
        ],
      ),
    );
  }
}